mcpField
G
go-uber-style-guide

go-uber-style-guide

github.com/metalagman開発2647 回インストール10 週間前に更新
リポジトリ

go-uber-style-guide について

Uber Go Style Guideに基づく、Go開発者向けのコーディングスキルです。エラー処理、並行処理、データ整合性、コード構成、検証方法を扱い、Goコードの作成とレビューを支援します。

主な機能

  1. 01エラー処理と並行処理の規則
  2. 02データ整合性とグローバル状態の指針
  3. 03コード構成と命名規則
  4. 04テスト、性能、ツールの実践

活用シーン

  1. 01ガイドに沿ってGoコードをレビュー
  2. 02安全で一貫したGo実装の作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/metalagman/agent-skills --skill go-uber-style-guide

インストール後、Claude Code で/go-uber-style-guideを入力して読み込まれたか確認します。

同梱ファイルassets/.golangci.ymlreferences/style.md

詳細

go-uber-style-guide

Go プログラミングのエキスパートとして、Uber Go Style Guide を専門としています。ユーザーが、クリーンで安全な、Uber が定める絶対的にイディオマティックなパターンに従ったコードを書けるよう支援します。

基本方針

これらは、正確性と安全性を確保するための、基本的かつ譲れないルールです。スタイルガイドの全文については、references/style.md を参照してください。

エラー処理
  • エラーの処理は一度だけ: 各エラーは最大一度だけ処理します。同じエラーをログに記録してから返してはいけません。
  • panic を避ける: 本番環境では panic を避けます。代わりにエラーを返します。panic は、真に回復不能な状態(例:nil の参照外し)や、プログラムの初期化時(起動の中止)に限って使用します。
  • main で終了する: os.Exit または log.Fatal* は main() 内でのみ呼び出します。呼び出しは最大一度にするのが望ましいです。それ以外の関数はすべてエラーを返さなければなりません。
  • 型アサーションの安全性: 型アサーションでは、必ず「comma ok」イディオム(value, ok := interface{}.(Type))を使用します。
  • エラーのラップ: 呼び出し元がエラーを照合できるようにラップする場合は、fmt.Errorf の %w を使用し、エラーの内容を隠す場合は %v を使用します。「failed to」という接頭辞は避けます。
並行処理
  • チャネルのサイズ: チャネルはバッファなし(サイズ 0)か、サイズ 1 にします。それ以外のサイズには、十分な根拠と慎重な検討が必要です。
  • ゴルーチンのライフサイクル: 「fire-and-forget」は決して行いません。すべてのゴルーチンには、予測可能な停止時点またはシグナルの仕組みが必要であり、呼び出し元がその終了を待てなければなりません。
  • init() 内でゴルーチンを起動しない: init() 関数からゴルーチンを起動してはいけません。ライフサイクルメソッドが明示されたオブジェクトを介して、バックグラウンドタスクを管理します。
  • アトミック操作: 型安全なアトミック操作には go.uber.org/atomic を使用します。
データの整合性とグローバル変数
  • 境界でスライスとマップをコピーする: 受け取ったスライスやマップを保存する場合はコピーします。内部状態を公開する場合は、返すものをコピーします。
  • 変更可能なグローバル変数を避ける: グローバル変数(関数ポインターを含む)を変更する代わりに、依存性注入を使用します。
  • シャドーイングをしない: Go の事前宣言済み識別子(例:error、string、make、new)を名前として使用してはいけません。go vet がクリーンに通るようにします。
コード構造
  • 一貫性が重要: 何よりも、パッケージ以上の範囲で一貫性を保ちます。
  • init() を最小限にする: 必要かつ決定的な場合を除き、init() は避けます。I/O、グローバル状態や環境状態の操作、実行順序への依存を行ってはいけません。
  • 構造体を明示的に初期化する: 必ずフィールド名を使用します(MyStruct{Field: value})。例外:フィールド数が 3 以下のテストテーブル。
  • nil スライスの意味: 空のスライスには nil を返します。空かどうかを確認するには len(s) == 0 を使います。var で宣言したスライスは、そのまま使用できます。

エキスパート向けガイダンス

以下は、可読性、保守性、パフォーマンスを高めるために推奨されるプラクティスです。

ポインターとインターフェース
  • インターフェースへのポインターを使わない: インターフェースは値として渡します。ポインターは、メソッドで基になるデータを変更する必要がある場合にのみ使用します。
  • コンパイル時のインターフェース適合性検証: 適切な場合は、var _ Interface = (*Type)(nil) を使用して、コンパイル時に適合性を検証します。
  • レシーバーの選択: ポインターレシーバーは、ポインターまたはアドレス指定可能な値にのみ使用します。値レシーバーはどちらにも使用できます。値レシーバーであっても、ポインターはインターフェースを満たせます。
並行処理と同期
  • ゼロ値のミューテックス: sync.Mutex と sync.RWMutex はゼロ値の状態で有効です。ミューテックスへのポインターは使用しません。構造体には非ポインターフィールドを使用します。
  • ミューテックスを埋め込まない: 非公開のものも含め、ミューテックスを構造体に埋め込んではいけません。
  • 同期: 複数のゴルーチンには sync.WaitGroup を、単一のゴルーチンには完了時にクローズする chan struct{} を使用します。
時間管理
  • time パッケージ: 時間に関するすべての操作には、常に "time" パッケージを使用します。
  • 時点と期間: 時点には time.Time を、期間には time.Duration を使用します。
  • 外部システム: 外部システムでは time.Time/time.Duration を使用します。使用できない場合は、単位を名前に含めた int/float64(例:Millis)、またはタイムスタンプに RFC 3339 形式の文字列を使用します。
  • 比較: 暦上の日数には .AddDate を、絶対的な24時間の期間には .Add を使用します。
パフォーマンス(ホットパスのみ)
  • fmt より strconv: プリミティブ型から文字列への変換には strconv を使用します。
  • 文字列からバイト列への変換: 固定文字列を []byte に変換するのは一度だけにし、再利用します。
  • 容量の指定: 再割り当てを最小限に抑えるため、可能な場合はマップとスライスの make() で容量を指定します。
コードスタイルと可読性
  • 行の長さ: 目安は99文字です。横スクロールが必要になるのを避けます。
  • グループ化: 関連する import、const、var、type 宣言をグループ化します。関数内で変数を隣接して宣言する場合は、まとめて宣言します。
  • インポートの順序: 2つのグループに分けます。標準ライブラリを先に置き、空行を挟んでその他を置きます。
  • パッケージ名: すべて小文字にし、アンダースコアを使わず、簡潔な単数形にします。「common/util/shared/lib」は使いません。
  • 関数名: MixedCaps を使用します。テストではグループ化のためにアンダースコアを使用できます。
  • インポートのエイリアス: パッケージ名がパスの末尾の要素と一致しない場合、または名前が競合する場合に限り使用します。
  • 順序: レシーバーごとにグループ化します。呼び出し順に並べます。エクスポートされた関数を先に置き、ユーティリティを最後に置きます。
  • ネスト: エラーや特殊なケースを先に処理します(早期リターン/コンティニュー)。
  • 不要な Else: 両方の分岐で変数を設定している if/else は、可能であれば単一の更新に置き換えます。
  • 非エクスポートのグローバル変数のプレフィックス: 非エクスポートのトップレベル var/const には _ を使用します(非エクスポートのエラーに付ける err プレフィックスは例外です)。
  • 埋め込み: 構造体の先頭に配置し、空行で区切ります。明確な利点があり、内部実装の漏えいやゼロ値/コピーのセマンティクスの変更を招かない場合に限り、埋め込みを使用します。
  • 変数宣言: 明示的な値には := を、デフォルトのゼロ値には var を使用します。スコープは最小限にします。
  • 名前のないパラメーター: 明確にするために、Cスタイルのコメント /* paramName */ を使用します。適切な場合は bool の代わりにカスタム型を使用します。
  • 生文字列: 複数行の文字列や引用符を含む文字列にはバッククォート(`)を使用します。
パターン
  • テーブル駆動テスト: tests スライスと tt ケース変数を使用します。give/want のプレフィックスを使用します。サブテスト内の複雑なロジックは避けます。
  • 関数オプション: コンストラクター/APIの任意引数が3つ以上ある場合に使用します。Option インターフェースと非エクスポートの options 構造体を使用します。

ツールと検証

  • ツール(Go 1.24+): プロジェクトローカルのツールを呼び出す際は、go tool <toolname> を優先します。
  • リンティング: 実行ツールとして golangci-lint を使用します。ベースラインとして assets/.golangci.yml の設定を使用します。
  • 構造体タグ: マーシャリングされる構造体(JSON、YAML)には、必ずフィールドタグを使用します。
  • リーク検出: ゴルーチンのリーク検出には go.uber.org/goleak を使用します。
  • フォーマット文字列: go vet による解析のため、フォーマット文字列は Printf の呼び出しの外で const として宣言します。
  • Printf の命名: 独自の Printf スタイル関数の末尾には f を付けます。

コメント