go-code-review について
Go 開発者向けのコードレビュー用スキルです。自動チェックと Go 固有の指針を組み合わせ、重要度別にレビュー結果をまとめます。
主な機能
- 01gofmt、go vet、golangci-lint による事前確認
- 02Go のスタイル、エラー、並行処理、安全性のチェック
- 03ルール名と行番号を添えた問題の指摘
- 04重要度別のレビュー結果整理
活用シーン
- 01マージ前の Go 変更レビュー
- 02HTTP サーバーの並行処理や終了処理の確認
- 03Must Fix、Should Fix、Nits に分けた指摘の整理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cxuu/ golang-skills --skill go-code-reviewインストール後、Claude Code で/go-code-reviewを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/review-template.mdreferences/WEB-SERVER.mdscripts/pre-review.sh詳細
Go コードレビューチェックリスト
互換性:
references/WEB-SERVER.mdのlog/slogの例を使用するには、Go 1.21 以降が必要です。
リソースのルーティング
assets/review-template.md- Must Fix、Should Fix、Nits のセクションを使ってレビュー結果を整形する場合に使用します。scripts/pre-review.sh- 手動レビューの前に実行し、gofmt、go vet、golangci-lint の結果を収集します。references/WEB-SERVER.md- 並行処理、コンテキスト、ロギング、エラー処理、シャットダウンの動作を組み合わせた HTTP サーバーをレビューする場合に読みます。
レビュープロセス
コードレビューの出力を整形する際は、
assets/review-template.mdを使用し、Must Fix/Should Fix/Nits の重大度グループで一貫した構成にします。
- まず
gofmt -d .とgo vet ./...を実行して、機械的に検出できる問題を確認します - ファイルごとに差分を読み、各ファイルについて以下のカテゴリを順に確認します
- 具体的な行番号とルール名を示して問題を指摘します
- すべてのファイルを確認した後、指摘事項を読み直し、本当に問題かどうかを検証します
- 指摘事項を重大度(must-fix、should-fix、nit)ごとにまとめます
検証:レビューを終えたら、差分をもう一度読み直し、指摘した問題がすべて実際の問題であることを確認します。具体的な行番号を示して根拠を説明できない指摘は削除します。
フォーマット
- gofmt:コードは
gofmtまたはgoimportsでフォーマットされています → go-linting
ドキュメント
- コメント文:コメントは説明対象の名前で始まり、ピリオドで終わる完全な文です → go-documentation
- ドキュメントコメント:エクスポートされた名前すべてにドキュメントコメントがあり、重要な非エクスポート宣言にもあります → go-documentation
- パッケージコメント:パッケージコメントは空行を挟まずに package 節の直前にあります → go-documentation
- 名前付き戻り値パラメーター:意味を明確にする場合(例:同じ型の戻り値が複数ある場合)にのみ使用し、裸の return を使えるようにするだけの目的では使用しません → go-documentation
エラー処理
- エラーの処理:
_でエラーを破棄せず、処理するか、返すか(例外的に)panic します → go-error-handling - エラー文字列:小文字で、句読点を含みません(固有名詞または頭字語で始まる場合を除く) → go-error-handling
- インバンドエラー:マジック値(-1、""、nil)を使わず、エラーまたは ok のブール値を伴う複数の戻り値を使用します → go-error-handling
- エラー処理のインデント:先にエラーを処理して return し、通常の処理経路のインデントを最小限に抑えます → go-error-handling
命名
- MixedCaps:
MixedCapsまたはmixedCapsを使い、アンダースコアは使いません。非エクスポート名はMAX_LENGTHではなくmaxLengthとします → go-naming - 頭字語:大文字・小文字の表記を統一します。
URL/url、ID/id、HTTP/http(例:ServeHTTP、xmlHTTPRequest) → go-naming - 変数名:スコープが狭い場合は短い名前(
i、r、`c)、広い場合は長い名前を使います → go-naming - レシーバー名:型名の 1~2 文字の略称(
Clientならc)を使い、this、self、meは使いません。メソッド間で表記を統一します → go-naming - パッケージ名:名前の重複を避けます(
chubby.ChubbyFileではなくchubby.Fileを使用)。util、common、miscは避けます → go-packages - 組み込み名を避ける:
error、string、len、cap、append、copy、new、makeをシャドーイングしないでください → go-declarations
並行処理
- ゴルーチンのライフタイム:ゴルーチンがいつ、または終了するかを明確にします。明らかでない場合は文書化します → go-concurrency
- 同期関数:非同期より同期を優先します。必要に応じて呼び出し側で並行処理を追加できるようにします → go-concurrency
- コンテキスト:最初のパラメーターにします。構造体には含めず、独自の Context 型は作成しません。不要だと思っていても渡します → go-context
インターフェース
- インターフェースの配置場所:実装側ではなく利用側のパッケージで定義し、生成側からは具象型を返します → go-interfaces
- 時期尚早なインターフェースを避ける:使用される前に定義しないでください。実装側で「モック用」に定義しないでください → go-interfaces
- レシーバーの型:変更する場合、同期用のフィールドを持つ場合、またはサイズが大きい場合はポインターを使用します。小さく不変の型には値を使用し、混在させないでください → go-interfaces
データ構造
- 空のスライス:
t := []string{}(nil ではない長さ 0 のスライス)よりも、var t []string(nil)を優先します → go-data-structures - コピー:ポインターやスライスのフィールドを持つ構造体のコピーには注意してください。
*Tメソッドのレシーバーを値でコピーしないでください → go-data-structures
セキュリティ
- 暗号論的乱数:キーには
math/randではなくcrypto/randを使用します → go-defensive - panic を避ける:通常のエラー処理にはエラーを返します。panic は真に例外的なケースでのみ使用します → go-defensive
宣言と初期化
- 関連するものをまとめる:関連する
var/const/typeは括弧付きブロックにまとめ、無関係なものは分けます → go-declarations - var と :=:意図的にゼロ値を使う場合は
var、明示的に代入する場合は:=を使用します → go-declarations - スコープを狭める:宣言を使用箇所の近くに移動し、if 初期化構文を使って変数のスコープを制限します → go-declarations
- 構造体の初期化:常にフィールド名を指定し、ゼロ値のフィールドは省略します。ゼロ値の構造体には
varを使用します → go-declarations -
anyを使用する:新しいコードではinterface{}よりanyを優先します → go-declarations
関数
- ファイル内の順序:型 → コンストラクター → エクスポートされたメソッド → 非エクスポートのメソッド → ユーティリティ → go-functions
- シグネチャの書式:複数行に折り返す場合は、すべての引数をそれぞれ別の行に置き、末尾にカンマを付けます → go-functions
- 名前のないパラメーター:曖昧な bool/int 引数には
/* name */コメントを追加するか、カスタム型を使用します → go-functions - Printf の命名:書式文字列を受け取る関数名は、
go vetのためにfで終わるようにします → go-functions
スタイル
- 行の長さ:厳格な上限はありませんが、極端に長い行は避け、任意の長さではなく意味のまとまりに沿って改行します → go-style-core
- 名前のない戻り値:短い関数でのみ使用し、中規模または大規模な関数では明示的な戻り値を使用します → go-style-core
- 値を渡す:バイト数の節約だけを目的にポインターを使用しないでください。小さく固定サイズの型は
*stringではなくstringを渡します → go-performance - 文字列の連結:単純な場合は
+、書式設定にはfmt.Sprintf、ループ内ではstrings.Builderを使用します → go-performance
ロギング
- slog を使用する:新しいコードでは、運用ログに
logやfmt.Printlnではなくlog/slogを使用します → go-logging - 構造化フィールド:ログメッセージでは fmt.Sprintf ではなく、静的文字列とキーと値の属性を使用します → go-logging
- 適切なレベル:開発者による追跡には Debug、注目すべきイベントには Info、回復可能な問題には Warn、失敗には Error を使用します → go-logging
- ログに秘密情報を含めない:PII、認証情報、トークンは決してログに記録しません → go-logging
インポート
- インポートグループ:標準ライブラリを先に記述し、空行の後に外部パッケージを記述します → go-packages
- インポートの別名:衝突する場合を除き避けます。衝突する場合は、ローカルまたはプロジェクト固有のインポートに別名を付けます → go-packages
- 空のインポート:
import _ "pkg"は main パッケージまたはテストでのみ使用します → go-packages - ドットインポート:テストで循環依存を回避する場合にのみ使用します → go-packages
ジェネリクス
- 使用する場面:複数の型で同一のロジックを共有し、インターフェースでは不十分な場合にのみ使用します → go-generics
- 型エイリアス:新しい型には型定義を使用し、エイリアスはパッケージの移行にのみ使用します → go-generics
テスト
- 例:使用方法を示す、実行可能な
Example関数またはテストを含めます → go-documentation - 役立つテスト失敗メッセージ:何が間違っていたか、入力値、got、want をメッセージに含めます。順序は
got != wantです → go-testing - TestMain:すべてのテストで共通のセットアップと後処理が必要な場合にのみ使用し、まずスコープを限定したヘルパーを優先します → go-testing
- 実際のトランスポート:HTTP をモックするよりも、
httptest.NewServerと実際のクライアントの組み合わせを優先します → go-testing
自動チェック
レビュー前に自動チェックを実行します:
bash scripts/pre-review.sh ./... # text output
bash scripts/pre-review.sh --json ./... # structured JSON output
または手動で実行します:gofmt -l <path> && go vet ./... && golangci-lint run ./...
上記のチェックリストに進む前に、問題を修正してください。リンターのセットアップと設定については、go-linting を参照してください。
関連スキル
- スタイルの基礎:書式に関する議論を解決する場合や、明瞭さ > シンプルさ > 簡潔さの優先順位を適用する場合は、go-style-core を参照してください
- リンターのセットアップ:golangci-lint を設定する場合や、CI に自動チェックを追加する場合は、go-linting を参照してください
- エラー戦略:エラーのラップ、センチネルエラー、または handle-once パターンをレビューする場合は、go-error-handling を参照してください
- 命名規則:識別子名、レシーバー名、またはパッケージ名とシンボル名の重複を評価する場合は、go-naming を参照してください
- テストパターン:テーブル駆動の構造、失敗メッセージ、またはヘルパーの使用状況についてテストコードをレビューする場合は、go-testing を参照してください
- 並行処理の安全性:ゴルーチンのライフタイム、チャネルの使用方法、またはミューテックスの配置をレビューする場合は、go-concurrency を参照してください
- ロギングの実践:ログの使用方法、構造化ロギング、または slog の設定をレビューする場合は、go-logging を参照してください
コメント
Markdown 対応