go-idiomatic について
Go Idiomatic は、リポジトリの変更やレビューを行う開発者向けに、固有の Go 規約を定めています。テーマ別に詳細な資料や関連スキルへ案内します。
主な機能
- 01エラー処理とログの規則
- 02コード構成の規約
- 03関数設計と命名の指針
- 04テーマ別資料への案内
- 05Go ツールの要件
活用シーン
- 01Go リポジトリのコード変更
- 02Go コード規約のレビュー
- 03特定テーマの参考資料を探す
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ o-marsters-1997/ my-claude-code --skill go-idiomaticインストール後、Claude Code で/go-idiomaticを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonevals/files/optional-field/go.modevals/files/optional-field/internal/user/user.goevals/files/refactor-store/go.modevals/files/refactor-store/helpers/helpers.goevals/files/refactor-store/store/store.goevals/files/server-settings/go.modevals/files/server-settings/cmd/app/main.goevals/files/server-settings/internal/server/server.goreferences/concurrency.mddatabase.mderrors.mdexec.mdhttp-client.mdlogging.mdmiddleware.mdoptional.mdpatterns.mdsecrets.mdvalue-vs-pointer.md詳細
Go のイディオマティックな書き方
このリポジトリにおける Go のルールです。一般的な Go の慣習と異なる点や、より明確に定めている点を示します。以下のルールはすべての変更に適用されます。詳しい説明と実例については、各リファレンスを参照してください。
参照先
先に適切なリファレンスを確認してください。
| 作業内容… | 参照先 |
|---|---|
| Goroutine、チャネル、同期プリミティブ、errgroup、リーク、競合状態 | references/concurrency.md |
センチネルやエラー型の追加、パッケージ間または HTTP レスポンスへのエラーの変換、エラーの発生元のログ記録、defer でのクリーンアップ、panic | references/errors.md |
| HTTP ミドルウェア:リクエストの Content-Type、CSRF、セッション Cookie の属性 | references/middleware.md |
| セッショントークンやリセットトークンの保存、パスワードのリセットや変更、カラムの暗号化 | references/secrets.md |
main やコンポーネントへのロガーの渡し方、ログレベルの選択、CLI 出力とログの使い分け | references/logging.md |
| インターフェース設計、ゼロ値、識別子型、型付き値セット、アンチパターン | references/patterns.md |
| テスト、ベンチマーク、ファジング、テスト用データベースの作成やレビュー | go-testing スキル |
オプションのフィールドや戻り値 — Option[T] を使う場面 | references/optional.md |
| ポインタレシーバーと値レシーバー、変更とオプション性の使い分け | references/value-vs-pointer.md |
サードパーティ API 用の Go HTTP クライアントの雛形作成、NewXxxClient の作成、送信 HTTP 呼び出しへの認証情報の付与 | references/http-client.md |
os/exec で git、gh などの CLI を実行する、--json 出力を解析する、テストで偽装する | references/exec.md |
| SQL でのデータ保存:ストアパッケージの境界、トランザクション、NULL、制約エラー、接続プールの設定 | references/database.md |
htmx 用の html/template のレンダリング:ページとフラグメントとリダイレクトの使い分け、HX-* ヘッダー、.tmpl ファイル | htmx-go-templates スキル |
エラーとログ
ほぼすべての変更でエラーを返すか、エラーを報告するため、これらのルールはエラー処理と明示されたタスクだけでなく、すべての Go 作業に適用されます。
fmt.Errorf("<verb> <noun>: %w", err)でラップします。エラー文字列は小文字にし、句読点や「failed to」は含めません。- エラーを処理するのは一度だけです。コンテキストを付けて返すか、呼び出しチェーンの最上位でログに記録します。両方は行いません。
- センチネルをエクスポートするのは、別パッケージの呼び出し元がそれに基づいて分岐する場合だけです。条件を検出した場所で定義し、依存関係のエラーはパッケージ境界で独自のエラーに変換します。
_ =でエラーを破棄してはいけません。クリーンアップのエラーは返すエラーに結合するか、返す先がない場合はWarnでログに記録します。panicはプログラマーエラーの場合に限ります。定数入力に対するMustヘルパーや、発生し得ないケースなどが該当します。- エラーの伝播が止まるコンポーネント(ハンドラー、ワーカー、長時間稼働するサービス)だけが、コンストラクターのフィールドとして注入された
*slog.Loggerを受け取ります。それより下位のコードはエラーを返し、ロガーを受け取りません。ロガーを作成するのはmainだけです。log.*、slog.Info、slog.Default()は呼び出しません。 - ログメッセージは固定とし、変数データは
errをエラー用のキーとして、snake_case のキーと値の属性に含めます。シークレットや個人データはログに記録しません。 - ユーザーが求めた出力は、ロガーではなく注入された
io.Writerに書き込みます。
通常の return fmt.Errorf(...) やログ出力には、これらのルールだけで十分です。センチネルやエラー型を追加する場合、エラーを HTTP レスポンスに変換する場合、ドライバーや送信呼び出しのエラーをラップする場合、クリーンアップのエラーを処理する場合は references/errors.md を参照してください。ロガーを組み込む場合、ログレベルを選ぶ場合、CLI 出力を分ける場合は references/logging.md を参照してください。
テスト
_test.go ファイルを作成、編集、またはレビューする場合は、go-testing スキルを読み込んでください。このスキルが、テスト用データベースを含め、Go のテストの書き方を定めています。何をテストするか(テストの種類、それぞれの価値、再利用可能なパターン)は、リポジトリに testing-policy がある場合は、それに従います。
コードの構成
- アプリケーションでは
mainをcmd/<app>/main.goに置き、依存関係の組み立てだけを行います。それ以外はすべてinternal/以下に置きます。pkg/はリポジトリ外からインポートされるライブラリモジュール用です。アプリケーションで使うと、存在しないパブリック API を示すことになります。 - 意味のある異なるパッケージ間で3回目に繰り返された時点で、共有ロジックを抽出します。2回目ではありません。1つのドメインに結び付いたヘルパーは、主な呼び出し元の隣にある
internal/に置きます。 - パッケージ名は、そのパッケージの役割を表す名前にします(
stringx、idgen、timeutil)。utilsは、多数のパッケージで使われ、internal/から何もインポートしない場合に限り使用できます。helpersとcommonは使用できません。適切な名前が必ず見つかります。 init()で設定するグローバルな*sql.DBのようなパッケージレベルの状態は使用しません。依存関係はコンストラクターを通じて渡します。mainで環境変数を一度だけ型付きの設定構造体に読み込み、検証します。不正な値があれば、それを必要とする最初のリクエスト時ではなく、起動時に終了します。コンストラクターには、構造体全体ではなく、使用するフィールドだけを渡します。cmd/以下からos.Getenvを呼び出してはいけません。
関数の設計
-
引数が3~4個を超える場合は、構造体にまとめるか、今後拡張するコンストラクターには関数型オプション(
opts ...Option)を使います。新しいオプションの追加には後方互換性がありますが、位置引数の追加にはありません。 -
複雑な引数は、呼び出しの中でコンストラクターを入れ子にするのではなく、呼び出し前に名前付きのローカル変数として宣言します。
sentAt := time.Now().Add(-24 * time.Hour) priority := Priority(3) client.Send(NewMessage(sender, recipient, sentAt, priority)) -
条件を確認したら早期にリターンします。正常系の処理はインデントせず、関数の末尾に置き、
returnの後にelseを付けません。if/else ifの連鎖ではなくswitchを使います。 -
変更を加える場合や、測定可能なほど大きな構造体にはポインターを使い、小さく不変の型には値を使います。「設定されていない可能性がある」という意味で
*Tを使ってはいけません。その場合はOption[T]を使います。
命名とコメント
関数には、返すものや実行する処理を表す名前(ParseConfig、IsExpired)を付け、ブール値には述語の名前(canRetry)を付けます。省略形は Go の慣習に従うものだけにします(ctx、err、id、r、w)。
コメントに値するものは ~/.claude/rules/comments.md で定めています。これが正式な基準であり、このスキルで内容を言い換えたり、緩めたりすることはありません。ファイルを編集する前に読み、行数の上限や、ドキュメントコメントをエクスポート対象の識別子に限るルールを含め、記載どおりに適用してください。internal/ はパブリック API ではありません。Go コードのコメントの品質をレビューする場合は、clean-comments スキルを使います。ファイルにある既存コメントの密度に合わせるよう指示してはいけません。
ツール
完了前に gofmt、goimports、go vet ./...、golangci-lint run を実行します。機械的なルールは、ここで言い直すのではなくリンターに任せます。既存の違反に //nolint を追加してはいけません。違反を修正するか、修正が済むまでそのルールを無効にしておきます。
関連項目
| スキル | 使用する場面 |
|---|---|
go-testing | テストの書き方:アサーション、代替実装、テーブル、テスト用データベース |
tdd | TDD サイクル、レッド・グリーン・リファクタリング、テストを先に書く方法 |
clean-comments | Go コード全体から説明的なコメントを監査して削除する |
improve-codebase-architecture | 構造上の改善点や浅いモジュールを特定する |
simplify | 実装後に変更したコードの品質、再利用性、効率性をレビューする |