rules-golang
Goコードの作成、レビュー、または修正を行う際に使用します。Goに特化したコーディングルールを提供し、rules-commonの汎用ルールをオーバーライドおよび拡張します。
description の原文を見る
Use when writing, reviewing, or modifying Go code — provides Go-specific coding rules that override and extend the universal rules from rules-common
SKILL.md 本文
Go コーディング規則
これらの規則は Go プロジェクトに適用されます。rules-common のすべての規則を継承し、Go の慣例が異なる特定のエントリをオーバーライドします。オーバーライドは [Overrides common: X.Y] でマークされており、理由を含みます。
この規則レイヤーは、Go を書く、またはレビューするための判断を必要とするガイダンスに焦点を当てています。フォーマット、静的解析、レース検出、およびその他の機械的チェックは、このスキルではなく検証ツール側に属しています。
新しい Go コード、特にコメント、名前、エラー、および構成のイディオムリファレンスとして Effective Go (https://go.dev/doc/effective_go) を使用してください。これを既存プロジェクトを書き直す許可ではなく言語ガイドとして扱ってください。既存コードについては、ローカルな慣例と現在のタスク範囲が優先されます。
AI エージェント向けスコープ
rules-golang は Go コードを書く、修正し、レビューするための AI エージェント規則セットです。現在のタスクで エージェント が生成する新しい Go コードとテストに対するデフォルトの制約を提供します。
既存の Go コード については、まず周辺のコードを読み、ディレクトリレイアウト、パッケージ境界、命名、レイアリング、およびテスト構成のローカルな慣例を保持してください。これらの規則は、既存プロジェクトを再形成し、機能するコードの名前を変更し、パッケージを再編成し、テストを移動するための許可ではありません。現在のリクエスト、受け入れられた仕様、失敗したテスト、またはパブリック API の影響が必要とする場合を除きます。
このスキルが所有しないもの
バックエンド アーキテクチャ、データベースまたはクエリセーフティポリシー、HTTP フレームワークの選択、デプロイメント形状、ロギングスタック、依存関係のバージョン、ディレクトリトポロジー、命名クリーンアップ、またはテストフレームワークの設定を指定するために rules-golang を使用しないでください。これらの懸念は実際のプロジェクトで重要になる可能性がありますが、Go 言語規則ではありません。
Go 以外の懸念を提起するのは、変更されたコードに見られ、現在のタスクに影響を与える場合のみです。それらを rules-golang 違反として提示するのではなく、別のレビュー懸念としてラベル付けしてください。
Go バージョン互換性
新しい言語機能、標準ライブラリ API、またはシンタックスを使用する前に、モジュールの go ディレクティブと toolchain ディレクティブを確認してください。既存のモジュールポリシーは互換性制約であり、提案ではありません。
受け入れられたタスクで必要でない限り、モジュールの Go バージョンを上げたり、toolchain ディレクティブを追加したり、より新しいコンパイラを必須にしたりしないでください。より新しい Go バージョンが必要な場合、別の互換性決定として、理由、影響を受けるファイル、およびロールバックパスを報告してください。
新しい API が単なる利便性のみである場合、現在の go ディレクティブに適合するローカルフォールバックを優先してください。新しい Go リリースがより短いスペリングを提供するだけという理由で コード を最新化しないでください。
Go セマンティック リスク チェックリスト
Go を書く、またはレビューするときは、スタイルのみの調査の前にセマンティック リスクを優先させてください。エラープロパゲーション、エラーラッピング、コンテキストプロパゲーション、リソースのクリーンアップ、ゴルーチンのライフサイクル、チャネルまたはミューテックス所有権、nil およびゼロ値の動作、型付き nil および nil インターフェイスの動作、短変数宣言シャドーイング、スライスおよびマップ所有権、インターフェイス境界、ジェネリクス、低レベルランタイム契約、およびテスト有効性を確認してください。
スタイルのみの調査は二次的です。正確性、リソース寿命、並行安全性、現在のタスクの可読性、またはパブリック API の動作に影響を与えない限り、命名、レイアウト、またはフォーマットの違いを昇格させないでください。
Go 抽象化ルール
インターフェイス、ラッパー、ヘルパー、ジェネリクス、および依存関係の間接化には現在の根拠が必要です。現在の動作、呼び出し元の置き換えニーズ、または確立されたプロジェクトパターンが置き換え、再利用、または分離を必要とする場合に それらを使用します。
将来の拡張、テスト利便性、または汎用 Go スタイルのためにこれらの構造を追加しないでください。より直接的な実装を最初に選択し、サポートされていない拡張のアイデアはスコープ外の観察として報告してください。
1. 名前、パッケージ、およびドキュメント
1.1 命名規則 [Overrides common: 1.1]
理由: Go の名前はパブリック API のように読まれますが、既存プロジェクトの慣例は汎用スタイルの設定よりも強力です。
- 新しいエクスポート API については、周辺パッケージに適合するイディオマティック Go の名前を使用します
- 現在のタスクまたはパブリック API の影響が変更を必要とする場合を除き、既存コード の既存命名パターンを保持します
- 近くの名前が汎用 Go の設定と異なるという理由だけで命名クリーンアップを実行しないでください
- 正確性、現在の変更の可読性、テスト、またはパブリック API に影響を与えない限り、命名のみの観察をスコープ外の観察として扱ってください
1.2 関数のサイズ [Overrides common: 1.2]
理由: 明示的なエラー処理は垂直方向のスペースを追加しますが、AI で生成された Go コードには具体的なレビュー可能性の制限が必要です。
- 新しい本番関数はデフォルトで 40 行以内に留めるべきです
- より長い関数にはテストデータ、ディスパッチテーブル、互換性ロジック、明確な順序フロー、または必要なエラーハンドリングなど、現在のタスク上の理由が必要です
- パラメータを転送するのみ、1 つの呼び出しをラップするのみ、同じアイデアの名前を変更するのみ、または読み手を飛び回させて 1 つの動作を理解させるだけのノー情報ヘルパーに関数を分割しないでください
- 実際の分岐を減らす、個別の概念を分離する、または主な動作をレビューしやすくするときのみヘルパーを抽出します
- エラー処理を失敗する可能性のある呼び出しの近くに保つ
1.3 ファイル構成 [Overrides common: 1.3]
理由: Go コードはパッケージファースト で読まれますが、古いプロジェクトとチームはこの規則が 1 つのレイアウトを課すには多すぎるほど異なります。
- 変更されるコードの近くで既に使用されているパッケージ、ファイル、ディレクトリ、およびテスト構成に従います
- このスキル単独からディレクトリレイアウト、パッケージ再形成、ファイル移動、またはテスト構成の変更を強制しないでください
- 新しいファイルについては、プロジェクトの慣例と現在のパッケージのローカルパターンに適合する名前と場所を選択します
- 無関係なパッケージまたはディレクトリの懸念を現在のタスク中に変更するのではなく、スコープ外の観察として報告します
1.4 ドキュメントとコメント
- 新しくエクスポートされた識別子には、識別子名で始まるドキュメントコメントが必要です
- 既存のエクスポートされた識別子は、現在のタスクがそれらのパブリック API、動作契約、または互換性プロミスを変更する場合を除き、コメントのみのクリーンアップを必要としません
- パッケージ docs はパッケージ名だけでは十分でない場合に目的と制約を説明します
- コメントは不変式、互換性制約、リソース寿命、並行所有権、または明白でないトレードオフを説明するべきです。明白なコード を言い直さないでください
- パブリック API ドキュメントを実装の詳細に埋めるのではなく、エクスポートされた境界に保つ
2. テストと TDD [Overrides common: 2.1]
理由: Go テストは シナリオが明示的で失敗出力が破損したケースを命名するときに最もレビューしやすくなります。
2.1 標準 testing パッケージを使用する
標準 testing パッケージを使用します。テスト関数は TestXxx(t *testing.T) です。
- Go Wiki table-driven tests ガイダンス: https://go.dev/wiki/TableDrivenTests に従います
- 複数の入力、境界条件、エラーパス、または予期される結果を含むシナリオマトリクスの場合、デフォルトで table-driven テストを選択します
testsスライスまたはマップを定義し、各ケースを反復処理し、t.Run(tt.name, ...)またはt.Run(name, ...)で名前付きサブテストを実行します- 各ケースには読み取り可能な名前、入力、予期される結果、およびシナリオを理解するために必要な動作コンテキストが含まれるべきです
- 失敗メッセージは got/want の表現または同等の診断の詳細を使用するべきです
- 単一の動作または直接的またはステップバイステップのテストが明確である順序付き動作については、table-driven テストを強制しないでください
- table ケースが並列サブテストとして実行される場合、共有される可変状態とループ変数キャプチャを避けます。pre-Go 1.22 モジュールまたはローカルコードベースが既にそのパターンに従う場合は、
t.Runの前にtt := ttを使用します
2.2 テストカバレッジ戦略 [Overrides common: 2.4]
理由: Go の型システムはいくつかのクラスの間違いをキャッチするため、エージェント が書いた効果的なテストはのみ形式的なテスト要件を満たすのではなく意味のある動作を証明する必要があります。
- ヘルパーの内部ではなく動作をテストします
- 現在の動作に関連する場合、happy パス、境界条件、エラーパス、リソース寿命、および並行リスクをカバーします
t.Run()を使用して、失敗がリグレッションした正確なシナリオを識別するようにします- ケースが共有される可変状態を共有しない場合のみ
t.Parallel()を使用します - 一時的なリソース、環境変数、およびテストごとに復元する必要があるプロセス全体のテスト変更には
t.Cleanup()を使用します - エラーパスについては、呼び出し元に見える契約がラッピング、センチネル、またはエラータイプを約束する場合、
errors.Isまたはerrors.Asでエラーアイデンティティを アサーション します。テキストそのものが契約である場合のみエラー文字列を比較します - 決定論的な同期を
time.Sleep()より優先させます。チャネル、sync.WaitGroup、コンテキスト キャンセル、またはプロジェクトが提供するフェイククロックを使用します。短いスリープまたはデッドラインは最後の手段のガードであり、同期メカニズムではありません - 失敗メッセージは入力、ブランチ、または破損したシナリオを名前付けするべきです
- 浅いテスト、実装テストのミラー、弱いアサーション、および非診断的な失敗を品質の低いテストとして扱い、書き直す必要があります
- システム自体をモックしないでください。モックは、合理的に直接実行できない外部依存関係にのみ使用します
*testing.Tまたはtesting.TBを受け入れるテストヘルパーは、失敗の位置と行番号がヘルパー本体ではなくテストケースを指すように、失敗を報告する前にt.Helper()を呼び出すべきです- 共有ディレクトリの代わりにテストごとのファイルシステムスクラッチスペースには
t.TempDir()を使用します - 環境の変更には
t.Setenvを使用し、t.Parallel()とプロセス全体の状態変更を組み合わせないでください - テスト本体を実行していないゴルーチンから
t.Fatal、t.Fatalf、またはt.FailNowを呼び出さないでください。チャネルまたは同期化された結果を通してテストゴルーチンに失敗を報告します
2.3 テスト命名
table-driven テストで説明的なサブテスト名を使用します: t.Run("empty input returns error", ...)。テスト名はシナリオを説明する文として読むべきです。
3. エラーと API [Overrides common: 5.6]
理由: Go はエラーを通常の値として扱うため、API 形状とエラーテキストの両方が保守性に影響を与えます。
3.1 エラーは値である
- 失敗する可能性のある関数からは、
errorを最後の戻り値として返します - 呼び出しの直後にエラーをチェックします
- エラー文字列は小文字で開始し、ドメインタームが必要でない限り句読点で終わりません
- 単純なエラーには
errors.New()を使用し、呼び出し元がチェーンを必要とする場合にはfmt.Errorf()に%wを使用します - 呼び出し元がそれらをブランチする必要がある場合のみ、センチネルエラーを導入します
3.2 エラーラッピング
- 各レイヤーでコンテキストを追加しますが、ラップされたエラーが既に言うことを繰り返さないでください
- ラップされたエラーを検査するには
errors.Is()とerrors.As()を使用します - エラー文字列をロジックを駆動するために比較しないでください
3.3 Panic はまれに
panicは回復不可能なプログラマーエラーまたは不可能な状態のためのものです- ライブラリは予期される失敗時にパニックを発生させる代わりにエラーを返します
- 明確に定義されたプロセスまたはゴルーチン境界でのみ
recoverを使用します - 境界で回復する場合、診断のために十分なコンテキストを保持し、予期される呼び出し元に見える失敗をエラーに変換します
3.4 パブリック API サーフェス
- エクスポートされた API を狭く保つ。別のパッケージが本当に必要になるまで名前をアンエクスポートします
- 呼び出し元が置き換えから利益を得ない限り、具体的な戻り値タイプを優先します
- 型セマンティクスが許す場合、ゼロ値を使用可能にします
3.5 Nil とインターフェイス値
- 型付き nil を
errorまたは他のインターフェイスとして返さないようにします。具体的な型を持つインターフェイス値は、具体的なポインタが nil でも nil インターフェイスではありません errorを返す関数から成功させるには、具体的なエラータイプへの nil ポインタの代わりに nil を明示的に返します- 呼び出し元が JSON、等価性チェック、または API 契約を通じてそれを観察できる場合は、nil フィールド、nil マップ、または nil スライスがパブリック API 契約の一部であるときのゼロ値の動作を保つ
3.6 戻り値とシャドーイング
- 短変数宣言
:=をスコープの決定として扱う。後のコードが観察することを期待している外側の err、結果値、コンテキスト、トランザクション、またはキャンセル関数をシャドーイングしていないことを確認します - 名前付き戻り値は、結果の意味を明確にするとき、または遅延クリーンアップが戻されたエラーを調整する必要があるときのみ使用します
- 小さな関数で名前付き結果値が明白である場合を除き、ネイキッドリターンを避けます。通常のエージェント が書いたコードで明示的に返します
4. コンテキスト、インターフェイス、およびレシーバー
4.1 context.Context 境界
- リクエストスコープの作業の最初のパラメータとして
context.Contextを明示的に渡します - 構造体に
context.Contextを格納しないでください - nil コンテキストを渡さないでください。
context.Background()またはcontext.TODO()はプロセス境界でのみ使用します - ブロッキング作業にキャンセルとデッドラインを伝播し、キャンセルが観察可能な結果である場合は
ctx.Err()を返すか、ラップします context.WithCancel、context.WithTimeout、またはcontext.WithDeadlineで派生コンテキストを作成するとき、所有権が意図的に移譲されてドキュメント化されない限り、defer cancel()をすぐに呼び出してタイマーリークを避けますcontext.Valueはリクエストスコープのメタデータのみに使用して API 境界を越える必要があり、オプションパラメータまたは必須依存関係には使用しません- コンテキスト値にはアンエクスポートされたキータイプを使用し、値が読まれる境界でタイプアサーションをチェックします
4.2 インターフェイス [Overrides common: 5.5]
- インターフェイスを実装されている場所ではなく使用されている場所で定義します
- インターフェイスを小さく保つ。通常、1 つまたは 2 つのメソッドで十分です
- 呼び出し元が置き換えから利益を得るときはインターフェイスを受け入れ、所有権が明確な場合は具体的なタイプを返します
- 複数の呼び出し元または実際のシームがそれを正当化するまで、インターフェイスを作成しないでください
any、interface{}、およびreflectはデコーディング、プラグイン統合、汎用アダプター、または互換性レイヤーなど、実際のアンタイプ化された境界でのみ使用します- 具体的なタイプ、小さなインターフェイス、型パラメータ、または型スイッチが動作を明確にするときは優先します
- 型付きコードを通じて動的タイプを広げることを避けます。境界がチェックされた後に行います
4.3 レシーバーの規律
- レシーバー名を短く、一貫性があり、タイプ名から派生させたものに保つ
- メソッドが状態を変更する場合または値をコピーすることが高くなる場合は、ポインタレシーバーを使用します
- 特定の理由がない限り、同じタイプでポインタレシーバーと値レシーバーを混在させないでください
- レシーバーメソッドセットはタイプの変更可能性を一目で明白にするべきです
5. 並行性とリソースのクリーンアップ
5.1 ゴルーチンのライフサイクル
- ゴルーチンをその寿命を所有している人を知らずに起動しないでください
- すべてのゴルーチンはシャットダウンパスと完了戦略を必要とします
- 生成ポイントでキャンセル、バックプレッシャー、エラープロパゲーションをドキュメント化します
- チャネルが所有権を明確にするときはそれを使用します。共有状態の場合はミューテックスを使用します
5.2 チャネルの規律
- 送信者がチャネルをクローズし、受信者ではありません
- 送信者がチャネルクローズを所有。複数のゴルーチンがチャネルを観察できるときオーナーをドキュメント化します
- nil チャネルは送受信で永遠にブロック。
selectケースを無効にするなど、意図的な場合のみそれを使用します - クローズされたチャネルへの送信またはクローズされたチャネルのクローズはパニックになります
- バッファ付きチャネルは特定のスループットまたは所有権の理由を必要とします
- チャネル操作が無限にブロック可能な場合は、
context.Done()でselectを使用します
5.3 共有状態の所有権
- 1 つのゴルーチンが状態を所有するか、
sync.Mutexまたはsync.RWMutexがそれを保護するか、チャネルが所有権を転送するかを決定します。これらのモデルを黙って混在させないでください - 初回使用後に
sync.Mutex、sync.RWMutex、sync.WaitGroup、sync.Once、またはアトミックフィールドを含む値をコピーしないでください WaitGroup.Addをゴルーチンを起動する前に呼び出し、ゴルーチン内でdefer wg.Done()を使用し、Waitとレースできるゴルーチン内で Add を避けます- 単純な共有状態で明確な所有権コメントを含む場合のみ
sync/atomicを使用します。複合不変式が重要な場合はロックを優先します - 同期フィールドまたは共有可変状態を含むタイプにはポインタレシーバーとポインタパラメータを使用します
- 呼び出し元が結果を変更して データレース または壊れた不変式を作成できる場合は、内部マップまたはスライスをコピーを返すか、所有権をドキュメント化して公開しないでください
- 返されたマップ、スライス、およびポインタフィールドを、API が呼び出し元が値を所有することを明確にドキュメント化しない限り、可変エイリアスとして扱います
5.4 リソースのクリーンアップ [Overrides common: 4.3]
理由: defer はクリーンアップを読み取り可能にしますが、リソース所有権が明白である場合のみです。
- リソース を取得した直後に
deferを使用します - ループ では、各反復がクリーンアップをスタックアップするのを避けるため、ヘルパー関数または明示的なクローズを使用します
- defer 引数は直ちに評価される。関数戻りで観察される最終値を必要とするクリーンアップのときのみ遅延クロージャを使用します
- 各反復が独自の関数境界を持つか、遅延呼び出しの数が意図的に制限されている場合を除き、ループで
deferを避けます - タイマーとティッカーのライフタイムを明示的に所有します。1 つの受信または 1 つの関数呼び出しを超える可能性があります
- 潜在的にブロッキング I/O をキャンセル、デッドライン、またはその両方とペアリングします
- エラーパスでさえ、開いているものをクローズします
5.5 低レベルランタイム契約
低レベルランタイム契約には、パニック回復、プロセス終了、unsafe、sync.Once、アトミック操作、タイマー再利用、ストリーム読み取り、クローズされたチャネル受信、非ブロッキングの select、および append キャパシティ動作が含まれます。タッチされたコードがその動作に依存する場合のみこれらを提起します。
そのような契約が重要な場合は、ノートを狭く保つ。影響を受ける操作、観察可能なリスク、およびローカルな修正を述べてください。このスキルを完全な Go ランタイムの落とし穴のカタログに
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- NSObjects
- リポジトリ
- NSObjects/specpowers
- ライセンス
- MIT
- 最終更新
- 2026/5/9
Source: https://github.com/NSObjects/specpowers / ライセンス: MIT