go-coding-standards について
go-coding-standardsは、Go開発者やコーディングエージェント向けの開発スキルです。慣用的な規約とコード品質チェックを扱い、ファイル構成、レシーバー、タグの詳細資料も用意しています。
主な機能
- 01インポートの分類と命名規則
- 02変数と構造体の初期化指針
- 03ネスト、順序、行長の規約
- 04レシーバー、時間、構造体タグの指針
- 05goimports、go vet、staticcheckによるチェック
活用シーン
- 01Goの慣用規約に沿ったコードレビュー
- 02宣言と構造体フィールドの整理
- 03コード完成前の品質チェック
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ eduardo-sl/ go-agent-skills --skill go-coding-standardsインストール後、Claude Code で/go-coding-standardsを入力して読み込まれたか確認します。
同梱ファイルreferences/file-organization.mdreferences/receivers-and-tags.md
詳細
Go コーディング規約
Effective Go、Go Code Review Comments、および本番環境で実証された慣用表現に基づく、Go の慣用的な規約です。
すべてのコードは、エラーなしで goimports、go vet、staticcheck(または golangci-lint run)を通過しなければなりません。
コミュニティのデフォルトです。プロジェクトのスキルまたはエージェント設定ルールが
go-coding-standardsを明示的に上書きする場合は、そちらが優先されます。
詳細な参考資料は必要に応じて読み込みます。
references/file-organization.md— 宣言のグループ化、ファイル内の順序、 長いシグネチャの分割。references/receivers-and-tags.md— レシーバーの一貫性と構造体タグの 例。
以下の概要だけでは不十分な場合に限り、参考ファイルを読んでください。
1. インポートの順序
インポートは空行で区切り、次の順序でグループ化します。
import (
// 1. Standard library
"context"
"fmt"
"log/slog"
"net/http"
// 2. External packages
"github.com/gorilla/mux"
// 3. Internal/project packages
"github.com/myorg/myproject/internal/service"
)
ドットインポートは絶対に使用しないでください。エイリアスは名前の競合を解決する場合に限り使用してください。
2. 命名
命名は go-naming スキルに従います。対象はパッケージ名、名前の重複、頭字語、ゲッター、レシーバー、エラー名、テスト名です。宣言に関する次の 2 つのルールは、ここに記載します。事前宣言された識別子(len、new、error、min、max)をシャドーイングしないでください。また、コードベースでその規約を使用している場合、非公開のパッケージレベル変数には _defaultTimeout のように _ 接頭辞を付けてもかまいません。
3. 変数宣言
トップレベル
トップレベルの宣言には var を使用します。式と型が一致する場合、型は指定しないでください。
// ✅ Good
var _defaultPort = 8080
var _logger = slog.Default()
// ❌ Bad — redundant type
var _defaultPort int = 8080
ローカル
- ローカル変数には
:=を優先して使用します。 - ゼロ値での初期化に意図があり、意味を持つ場合に限り
varを使用します。
// ✅ Good — zero value is meaningful
var buf bytes.Buffer
// ✅ Good — short declaration
name := getUserName()
4. 構造体の初期化
フィールド名を必ず使用し、意味を持つ場合を除いてゼロ値のフィールドは省略します。位置指定リテラルは、フィールドの追加や並べ替えによって気付かないうちに壊れるためです。
// ✅ Good
user := User{Name: "Alice", Email: "[email protected]"}
// ❌ Bad — positional
user := User{"Alice", "[email protected]", 0}
5. ネストを減らす
エラーや特殊なケースを最初に処理して早期リターンし、正常系の処理が左端から始まるようにします。if がすでにリターンする場合は else を省略し、デフォルト値を代入してから上書きする方法を優先してください。
// ✅ Good — guard clauses; no else
for _, v := range data {
if !v.IsValid() {
continue
}
if err := v.Process(); err != nil {
return fmt.Errorf("process %s: %w", v.ID, err)
}
}
a := 10 // default, then override
if condition {
a = 20
}
6. グループ化と順序
- 関連する
constとvarの宣言は、1 つの括弧付きブロックにまとめます。 - ファイル内の順序は、定数と変数、コンストラクター、公開メソッド(アルファベット順ではなく重要度順)、非公開メソッド、ヘルパーとします。
- メソッドは、それが属する型のすぐ後に配置します。
7. 行の長さ
目安は 99 文字です。長いシグネチャはパラメーターごとに改行し、閉じ括弧は独立した行に置きます。例:
references/file-organization.md。
8. defer の使用
クリーンアップには defer を使用します。リソースを取得した時点で意図が明確になります。
mu.Lock()
defer mu.Unlock()
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("open %s: %w", path, err)
}
defer f.Close() // read-only; check Close errors on files you write
9. 列挙型
ゼロ値は明示的な Unknown センチネル用に確保します。これにより、設定されていない値が実際の状態として扱われるのを防げます。
type Status int
const (
StatusUnknown Status = iota
StatusActive
StatusInactive
)
10. time パッケージを適切に使用する
- 期間には生の整数ではなく、
time.Durationを使用します。 - 時点には
time.Timeを使用します。time.Now().Sub(start)ではなくtime.Since(start)を使用します。 - 形式上
time.Durationを保持できない場合(JSON、YAML)は、フィールド名に単位を含めます。例:TimeoutSeconds int。変換は境界部分で行います。
// ✅ Good
func poll(interval time.Duration) { ... }
poll(10 * time.Second)
// ❌ Bad
func poll(intervalSecs int) { ... }
poll(10)
11. レシーバー
型ごとにレシーバーの種類を 1 つ選び、すべてのメソッドで統一してください。メソッドセットは値の保持方法によって変わるため、混在させないでください。メソッドが値を変更する場合、構造体が sync.Mutex などコピー不可のフィールドを持つ場合、構造体が大きい場合、または別のメソッドでポインタが必要な場合は、ポインタレシーバーを使用します。小さく不変の型には値レシーバーを使用します。レシーバー名は型名に基づく 1 文字または 2 文字(s *Server)とし、すべてのメソッドで統一してください。this や self は使用しないでください。例:references/receivers-and-tags.md。
12. 構造体タグ
コンパイラーはタグをチェックしないため、誤字があっても気づきません。
- シリアライズ境界を越える型のすべてのフィールドに、名前がすでに一致していてもタグを付けます。
- プロセスの外に絶対に出してはならないものには
json:"-"を付けます。非公開フィールドは何も通知されずにスキップされるため、見落としのように見えてしまいます。 omitemptyでは「未設定」と「ゼロ値」を区別できません。その区別が重要な場合は、ポインターまたはラッパーを使います。omitemptyは構造体を省略しません。time.Timeのようなフィールドには、Go のゼロ値とIsZero()を尊重するomitzero(Go 1.24 以降)を使います。go vetを実行します。structtagチェックで不正なタグを検出できます。
13. 関数の構成
- オペランドが3つ以上ある条件では、各要素に名前(
isOwner、isAdmin)を付け、ifがビジネスルールとして読めるようにします。 - 最初に
ctx context.Context、次に入力、最後にオプションを置きます。 - 引数が4つを超える場合、または同じ型の引数が複数並ぶ場合は、オプション構造体か関数オプションを使います。どちらも go-design-patterns スキルが担当します。
- 名前なし戻り値は、すべての戻り値を一目で確認できる短い関数でのみ使います。
検証チェックリスト
コードを完成と見なす前に、次を確認します。
goimportsがエラーなく実行されるgo vet ./...が成功するgolangci-lint runが成功する(設定されている場合)- 組み込み識別子をシャドーイングしていない
- すべてのインポートが適切にグループ化され、順序付けられている
- 構造体の初期化でフィールド名を使用している
- 不要なネストや else ブロックがない
- 型のすべてのメソッドでレシーバーの種類が一貫している
- シリアライズされる構造体フィールドすべてに明示的なタグが付いている