mcpField
G
go-service

go-service

github.com/brojonat開発139 回インストール2 週間前に更新
リポジトリ

go-service について

Go Service は、標準ライブラリ、SQL、コマンドラインツールを使った Go マイクロサービス開発向けのスキルです。依存性注入、HTTP ハンドラー、構造化ログ、データベースコード生成、テスト手順を扱います。

主な機能

  1. 01標準ライブラリによるサービス構築
  2. 02HTTP ミドルウェアの合成
  3. 03依存関係の明示的な受け渡し
  4. 04slog による構造化ログ
  5. 05sqlc による型安全なコード生成
  6. 06合成可能なコマンドラインの構築

活用シーン

  1. 01Go マイクロサービスの構成設計
  2. 02HTTP ハンドラーとミドルウェアの実装
  3. 03SQL スキーマ変更後のコード生成
  4. 04サービス用 CLI の構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/brojonat/llmsrules --skill go-service

インストール後、Claude Code で/go-serviceを入力して読み込まれたか確認します。

詳細

Go Service

標準ライブラリ、SQL 用の sqlc、コマンド用の urfave/cli、構造化ログ用の slog を使用した、本番環境向けの Go マイクロサービスです。

基本原則

  • 一つのことをうまく行う:各コンポーネントの責務は一つにします
  • 複雑さよりシンプルさを重視する:プレーンな JSON、標準 SQL、環境変数を使用します
  • 組み合わせる:パイプ処理や標準インターフェースに適した設計にします
  • 依存関係を明示する:グローバル変数やシングルトンを使わず、すべてをパラメーターとして渡します

プロジェクト構成

.
├── cmd/
│   ├── server/          # Backend service entry point
│   └── client/          # CLI entry point
├── cli/                 # CLI implementation
├── client/              # Public client library
├── internal/            # Internal packages
│   └── db/             # Generated code (from sqlc)
├── migrations/          # SQL schema migrations
├── queries/             # SQL queries for sqlc
├── examples/            # Usage examples
├── testdata/            # Test fixtures
├── Makefile
├── .air.toml           # Air configuration
├── sqlc.yaml           # sqlc configuration
├── go.mod
├── README.md
└── CHANGELOG.md

ハンドラー関数のパターン

http.Handler を返す関数を記述します(Mat Ryer のアプローチに従います)。

func handleListWallets(store TransactionStore, logger *slog.Logger) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()

        wallets, err := store.ListWallets(ctx)
        if err != nil {
            logger.ErrorContext(ctx, "failed to list wallets", "error", err)
            http.Error(w, "internal error", http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(wallets)
    })
}

ミドルウェアの組み合わせ

type adapter func(http.Handler) http.Handler

// adaptHandler applies adapters in reverse order so the first is outermost
func adaptHandler(h http.Handler, adapters ...adapter) http.Handler {
    for i := len(adapters) - 1; i >= 0; i-- {
        h = adapters[i](h)
    }
    return h
}

// Usage:
mux.Handle("GET /wallets", adaptHandler(
    handleListWallets(store, logger),
    withRequestID(),
    withLogging(logger),
    withMetrics(promRegistry),
    withJWTAuth(jwtSecret),
))

依存性注入

// Bad: hidden dependency on global
var db *sql.DB
func SaveTransaction(txn *Transaction) error {
    _, err := db.Exec("INSERT INTO transactions ...")
    return err
}

// Good: explicit dependencies
type TransactionStore interface {
    Save(ctx context.Context, txn *Transaction) error
}

type PostgresStore struct {
    db *sql.DB
}

func NewPostgresStore(db *sql.DB) *PostgresStore {
    return &PostgresStore{db: db}
}

// Dependencies are clear at construction time
store := NewPostgresStore(db)
poller := NewWalletPoller(solanaClient, store, natsConn)

slog による構造化ログ

func setupLogger(level slog.Level) *slog.Logger {
    opts := &slog.HandlerOptions{Level: level}
    return slog.New(slog.NewJSONHandler(os.Stderr, opts))
}

// Most logs at DEBUG level
logger.DebugContext(ctx, "polling wallet", "wallet", walletAddress, "last_slot", lastSlot)

// INFO for lifecycle events only
logger.InfoContext(ctx, "server started", "addr", addr, "version", version)

// ERROR for failures
logger.ErrorContext(ctx, "failed to store transaction", "error", err, "signature", sig)

LOG_LEVEL 環境変数で詳細度を制御します。本番環境ではデフォルトを WARN、開発環境では DEBUG にします。

sqlc による SQL

SQL を記述すると、型安全な Go コードが生成されます。

# sqlc.yaml
version: "2"
sql:
  - engine: "postgresql"
    queries: "queries/"
    schema: "migrations/"
    gen:
      go:
        package: "db"
        out: "internal/db"

スキーマを変更したら必ず再生成し、生成されたコードをコミットしてください。

エラー処理

// Always handle errors
txns, err := client.GetTransactions(ctx)
if err != nil {
    return fmt.Errorf("failed to get transactions: %w", err)
}

urfave/cli による CLI

環境変数への自動バインドとヘルプ機能を備えた、シンプルで組み合わせやすいコマンドラインインターフェースです。

開発ワークフロー

  1. 計画:まずインターフェースを設計します
  2. テストファースト(TDD):テストを記述し、最小限のコードを書いてからリファクタリングします
  3. サーバー+クライアント:サーバー機能を追加したら、クライアントメソッドと CLI サブコマンドも追加します
  4. Makefile:make test、make lint、make dev、make build-server
  5. ホットリロード:開発には Air を使用します
  6. リンティング:厳格な設定の golangci-lint を使用し、警告をすべて修正します

Unix の哲学

  • デフォルトでは静かにする:エラーや重要なイベントがある場合にのみ出力します
  • 標準出力に JSON を出力する:機械可読な出力を使用し、人間向けには --format=table|json|csv を使います
  • エラーは標準エラーに出力する:パイプ処理に備えて標準出力を汚しません
  • 終了コード:0 は成功、0 以外はエラーです

コメント