--- name: go-specialist description: | Go言語の設計・実装・レビューを担うスペシャリストスキル。 堅牢で慣用的なGoコードを `references/go-practices.md` の規約に準拠して生成する。 以下の状況で積極的にトリガーすること: - 「Goで書いて」「Goのコードを実装して」「.goファイルを作って」 - 「このGoコードをレビューして」「Goの実装をチェックして」「コードの品質を見て」 - 「Goのパッケージ設計を相談したい」「構成をどうすべきか」 - 「既存のGoコードをリファクタして」「この実装を改善して」 - 「go-specialist スキル」の明示実行 - 「goroutineの使い方は?」「error wrappingのベストプラクティスは?」などGo固有の技術質問 - 「CLIツールをGoで作りたい」「APIサーバーをGoで書きたい」などGo実装を含む依頼 - 「go.modの管理方法」「パッケージ構成の相談」などGoプロジェクト構成の相談 - 「テーブル駆動テストの書き方」「テストをGoで書いて」などGoテストの依頼 トリガーしないケース: - Bash/Python/Rust等の他言語のCLIツール開発 → 各言語の専門スキルへ - go installで入れたツールの使い方だけの話(スキル不要で直接回答可能) - Goに依存しない一般的なアルゴリズムの質問 argument-hint: "[ファイルパス or 要件の説明]" --- # Go Specialist Go言語の設計・実装・レビューを行う専門スキル。 `references/go-practices.md` を規約の源泉とし、慣用的で堅牢なGoコードを生成する。 ## 必須リファレンス **作業開始前に必ず `references/go-practices.md` を読み込むこと。** 命名規則・エラーハンドリング・並行処理・テスト・セキュリティなど、すべての規約がこの文書に定義されている。 | ファイル | 内容 | |---|---| | `references/go-practices.md` | 全モードで必読のコーディング規約(Go 1.24+対応) | ## モード判定 冒頭でユーザーの依頼からモードを判定する。複数該当・あいまいな場合のみ推奨案を含む複数の選択肢を提示してユーザーに確認する。 | キーワード例 | モード | |---|---| | 作って / 書いて / 実装して / 新規 / CLIツール / APIサーバー | Mode 1: 設計・実装 | | レビュー / チェック / 検証 / 改善 / 品質 | Mode 2: レビュー | | リファクタ / 書き直して / モダンに / 整理して | Mode 3: リファクタリング | | 教えて / 使い方 / ベストプラクティス / 違いは | Mode 4: 技術相談 | --- ## Mode 1: 設計・実装 新規Goコードを設計・実装する。 ### 手順 1. **要件の把握**: `$ARGUMENTS` またはユーザーの依頼から、目的・入出力・パッケージ構成を整理する 2. **リファレンス読込**: `references/go-practices.md` を読み込む 3. **設計**: パッケージ構成・型設計・インターフェース・エラー戦略を決定する 4. **実装**: リファレンスの規約に準拠してコードを書く 5. **検証**: `go vet` / `staticcheck` / `go test -shuffle on -race -cover ./...` の実行はサブエージェントに委譲し、メインには合否と失敗時の要点(落ちたテスト名・主要エラー)だけを戻させる。修正はメインで行い、全パスするまで検証は都度委譲して繰り返す。単一ファイルの軽微な修正など出力が少量に収まる場合は、委譲せずメインで直接実行してよい ### 実装時の必須チェックリスト リファレンスに加え、以下を常に意識する: - **エラーは必ずチェック**: `err` を `_` に捨てない — 無視されたエラーは原因不明の障害を招く。early returnパターンを徹底 - **エラーをラップしてコンテキストを追加**: `fmt.Errorf("操作名: %w", err)` — 元のエラー情報を保持し、`errors.Is/As` での判定を可能にする - **エクスポートされる識別子にはGodocコメント**: 英語で、識別子名から始める — `go doc` やエディタ補完でAPIドキュメントとして表示される - **構造体フィールドのjsonタグはsnake_case**: `json:"field_name"` — REST APIのJSON慣例に合わせ、フロントエンドとの一貫性を保つ - **スライスの事前キャパシティ確保**: サイズが予測できる場合は `make([]T, 0, n)` — `append` の再割り当てとコピーコストを抑える - **文字列結合は `strings.Builder`**: ループ内での `+` 結合は毎回新しい文字列を割り当てるため O(n²) になる - **goroutine起動時は `sync.WaitGroup` で管理**: 起動したら必ず完了を待つ手段を用意 — 待機なしだとmain終了時にgoroutineが途中で打ち切られる - **共有リソースへのアクセスは `sync.Mutex` で保護**: mapへの並行書き込みはランタイムpanicになる - **`context.Context` を最初の引数に**: キャンセルやタイムアウトを呼び出しチェーン全体に伝搬させるGoの標準パターン - **`log.Fatalf` ではなく `log.Panicf`**: `log.Fatalf` は `os.Exit(1)` を呼ぶためdeferブロックが実行されず、リソースリークの原因になる - **テストポートは `13000`, `28080` のように競合しにくい番号**: `3000`, `8080` は他のアプリと競合しやすく、CIでテストが不安定になる ### プロジェクト構成の基本パターン ``` project/ ├── cmd/ │ └── appname/ │ └── main.go # エントリーポイント ├── internal/ # 外部から参照されない実装 │ ├── handler/ │ ├── service/ │ └── repository/ ├── pkg/ # 外部に公開するパッケージ(必要な場合のみ) ├── go.mod ├── go.sum └── README.md ``` CLIツールの場合: - `cmd/` 配下にサブコマンドごとのエントリーポイント - フラグ解析は `flag` パッケージまたは `cobra` 等を用途に応じて選択 - `internal/` にビジネスロジックを分離し、`main.go` は薄く保つ ### インターフェース設計の原則 - **インターフェースは利用する側で定義**: 提供側で大きなインターフェースを定義しない - **インターフェースは小さく保つ**: 1-3メソッドが理想。`io.Reader` が良い手本 - **具体的な型を返し、インターフェースを受け取る**: "Accept interfaces, return structs" --- ## Mode 2: レビュー 既存Goコードの品質をレビューする。 ### 手順 1. **対象の特定**: `$ARGUMENTS` のパスまたはユーザー指示からレビュー対象を決定 2. **リファレンス読込**: `references/go-practices.md` を読み込む 3. **コード読込**: 対象ファイルを読み込む 4. **静的解析実行**: 利用可能であれば `go vet` / `staticcheck` の実行をサブエージェントに委譲し、結果(指摘一覧)を収集する。対象が単一ファイルのレビューであれば、委譲せずメインで直接実行してもよい 5. **手動レビュー**: 以下の観点で評価 ### レビュー観点 | カテゴリ | チェック項目 | |---|---| | **命名** | mixedCaps / パッケージ名の適切さ / エクスポート判定の妥当性 | | **エラー処理** | エラー無視の有無 / `%w` でのラップ / エラーメッセージの具体性 | | **関数設計** | 単一責任 / 引数の数(3つ以下が目安) / 名前と処理の一致 | | **並行処理** | WaitGroupの使用 / Mutex保護 / goroutineリーク / contextの伝搬 | | **テスト** | テーブル駆動テスト / t.Parallel() / エッジケースのカバー / 外部依存のモック | | **パフォーマンス** | スライスのキャパシティ / strings.Builder / 不要なアロケーション | | **セキュリティ** | 入力バリデーション / SQLインジェクション / ハードコード秘匿情報 | | **パッケージ** | 循環依存 / internalの活用 / go mod tidyの必要性 | | **コメント** | Godocコメント(英語) / 「なぜ」の説明 / 古いコメントの残存 | ### レポート形式 ```markdown ## レビュー結果: <ファイル名> ### 総評 (1-2文で全体の品質レベルと最も重要な改善点) ### 問題点 - **[重大]** 〜(即座に修正すべき問題) - **[推奨]** 〜(品質向上のための改善提案) - **[軽微]** 〜(あれば望ましい程度の指摘) ### 静的解析結果 (go vet / staticcheck を実行した場合のみ) ### 良い点 (規約に準拠している箇所、工夫されている箇所) ``` --- ## Mode 3: リファクタリング 既存Goコードをリファレンスの規約に沿って書き直す。 ### 手順 1. **対象の読込**: 現在のコードを読み込み、機能と意図を把握する 2. **リファレンス読込**: `references/go-practices.md` を読み込む 3. **差分分析**: 現在の実装とリファレンス規約のギャップを洗い出す 4. **リファクタ計画の提示**: 変更内容を箇条書きで提示し、ユーザーの承認を得る 5. **実装**: 承認を得た範囲でリファクタリングを実施 6. **検証**: `go vet` / テスト実行をサブエージェントに委譲し、既存の動作が維持されていることを確認する。出力が少量に収まる小規模なリファクタでは、委譲せずメインで直接実行してよい ### リファクタリングの優先順位 1. エラーハンドリング(エラー無視の解消、`%w` によるラップ) 2. 並行処理の安全性(race condition、goroutineリーク) 3. セキュリティ(入力バリデーション、SQLインジェクション防止) 4. 関数設計(単一責任への分割、引数の整理) 5. 命名規則・コーディングスタイル 6. パフォーマンス(不要なアロケーション、strings.Builder) 機能変更は行わない。動作が変わる可能性がある場合は明示的に警告する。 --- ## Mode 4: 技術相談 Go言語に関する技術質問に回答する。 ### 対応範囲 - 言語機能(generics、型アサーション、型スイッチ、埋め込み等) - 並行処理パターン(goroutine、channel、select、context、errgroup) - エラー設計(sentinel error、カスタムエラー型、errors.Is/As) - テストパターン(テーブル駆動、サブテスト、モック、httptest) - パッケージ設計(internal、依存関係、循環依存の解消) - パフォーマンス(pprof、ベンチマーク、メモリアロケーション) - ツールチェーン(go mod、go generate、go build タグ) - Go 1.22+のループ変数セマンティクス ### 回答方針 - 具体的なコード例を含める - 「なぜそうすべきか」の理由を簡潔に添える - 落とし穴や注意点があれば明示する - リファレンスの規約に関連する場合はその旨を伝える --- ## 共通の品質基準 すべてのモードで以下を基準とする: ### 静的解析の活用 利用可能なツールを積極的に使う。プロジェクト全体(`./...`)への実行は出力が大きくなりやすいため、サブエージェントに委譲し、メインには指摘の要約だけを戻させるとよい: ```bash go vet ./... staticcheck ./... ``` `gosec` が利用可能な場合はセキュリティチェックにも使用: ```bash gosec ./... ``` テスト用のダミー値など明らかに問題が無い箇所についてのみ `// #nosec` コメントの使用を許可する。 ### テスト実行 コード変更後は以下のオプションでテストを実行する。実行自体はサブエージェントに委譲し、メインには合否と失敗の要点だけを戻させ、修正はメインで行う: ```bash go test -shuffle on -race -cover ./... ``` - `-shuffle on`: テスト順序のランダム化 - `-race`: 競合状態の検出 - `-cover`: カバレッジの確認 ### Go Modules管理 - 不要な依存を残さない: `go mod tidy` で整理 - 依存バージョンは明示的に管理 - `go.sum` は常にコミットに含める