mcpField
G
golang

golang

github.com/saisudhir14開発9525 回インストール30 週間前に更新
リポジトリ

golang について

Go 開発向けのスキルで、Google、Uber、Go チームの実践例に基づくガイダンスを Go 1.25 向けにまとめています。一般的な開発テーマを扱い、専門分野別のサブスキルと参考資料も含みます。

主な機能

  1. 01エラー処理と並行処理の指針
  2. 02命名、インポート、データ構造の実践
  3. 03テストとパフォーマンスの推奨事項
  4. 04Lint、プロジェクト構成、セキュリティ
  5. 05Go 1.25 の機能と注意点

活用シーン

  1. 01Go コードの保守性レビュー
  2. 02Go プロジェクトの規約策定
  3. 03並行処理とエラー処理の確認
  4. 04Go のテストと Lint の準備

インストール

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

$npx skills add https://github.com/saisudhir14/claude-skills --skill golang

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
LICENSE
references/
testing.md
error-handling.md
performance.md
concurrency.md
patterns.md
gotchas.md

詳細

Go のベストプラクティス

Google、Uber、Go チームの本番環境向けパターンです。Go 1.25 に対応しています。

サブスキル:skills/go-error-handling、skills/go-concurrency、skills/go-testing、skills/go-performance、skills/go-code-review、skills/go-linting、skills/go-project-layout、skills/go-security。詳細なリファレンスはreferences/にあります。

基本原則

読みやすいコードでは、次の属性をこの順に重視します。

  1. 明瞭さ:目的と理由が読み手に明確に伝わる
  2. シンプルさ:最もシンプルな方法で目的を達成する
  3. 簡潔さ:ノイズに対する情報量が多い
  4. 保守性:正しく変更しやすい
  5. 一貫性:周囲のコードベースに沿っている

エラー処理

完全なガイド:skills/go-error-handling/SKILL.md | リファレンス:references/error-handling.md

  • エラーを返し、本番コードでは panic を発生させない
  • 呼び出し元でerrors.Is/errors.Asを使う必要がある場合は**%wでラップ**し、境界では%vを使う
  • コンテキストは簡潔にする:「failed to create new store: %w」ではなく「new store: %w」
  • エラーは一度だけ処理する:同じエラーをログに記録してから返さない
  • エラー文字列:小文字で、句読点を付けない
  • エラー処理のフローをインデントする:最初にエラーを処理し、正常系のインデントを最小限にする
  • 複数の独立したエラーには**errors.Join**(Go 1.20 以降)を使う
  • センチネルエラー:変数にはErrの接頭辞、型にはErrorの接尾辞を付ける
if err != nil {
    return fmt.Errorf("load config: %w", err)
}

並行処理

完全なガイド:skills/go-concurrency/SKILL.md | リファレンス:references/concurrency.md

  • チャネルのサイズ:0(バッファなし)または1。それ以外は理由を明記する
  • ゴルーチンのライフタイムを文書化する:いつ、どのように終了するかを記載する
  • エラーを返すゴルーチンには、手動のsync.WaitGroupより**errgroup.Groupを使う**
  • 同期関数を優先する:並行処理は呼び出し元に任せる
  • ミューテックスのゼロ値:ポインターを使わず、公開構造体に埋め込まない
  • 型付きアトミック(Go 1.19 以降):atomic.Int64、atomic.Bool、atomic.Pointer[T]
  • sync.Map(Go 1.24 以降):互いに異なるキー集合ではパフォーマンスが大幅に向上
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(10)
for _, item := range items {
    g.Go(func() error { return process(ctx, item) })
}
return g.Wait()

命名

  • 常に MixedCaps を使う:アンダースコアは使わない(MAX_LENGTHではなくMaxLength)
  • 頭字語:大文字・小文字の使い方を統一する(Url、Id、HttpではなくURL、ID、HTTP)
  • 短い変数名:スコープに応じた長さにする(ループではi、グローバル変数ではDefaultTimeout)
  • レシーバー名:1~2文字の略称を使い、メソッド間で統一する。this/selfは使わない
  • パッケージ名:小文字の一語にし、util/common/miscは使わない
  • 重複を避ける:http.HTTPServeではなくhttp.Serve、c.WriteConfigToではなくc.WriteTo
ポインターレシーバーと値レシーバー
ポインターレシーバー値レシーバー
レシーバーを変更する小さく不変の構造体
大きな構造体状態を変更しない
sync.Mutexを含むマップ、関数、またはチャネル
他のメソッドとの一貫性基本型

インポート

import (
    "context"
    "fmt"

    "github.com/google/uuid"
    "golang.org/x/sync/errgroup"

    "yourcompany/internal/config"
)
  • 3つのグループに分ける:標準ライブラリ、外部、内部(空行で区切る)
  • 名前の衝突を避ける場合に限り、別名を付ける
  • 循環依存のあるテストファイルを除き、ドットインポートは使わない
  • ブランクインポート(import _ "pkg")は、main またはテストでのみ使う

モジュール管理(Go 1.24 以降)

ツールディレクティブを使って、ツールの依存関係をgo.modで管理します。

tool (
    golang.org/x/tools/cmd/stringer
    github.com/golangci/golangci-lint/cmd/golangci-lint
)
go get -tool golang.org/x/tools/cmd/stringer  # add
go tool stringer -type=Status                  # run
go get tool                                    # update all
go install tool                                # install to GOBIN

構造体

  • 初期化時には常にフィールド名を指定する(位置指定では変更時に問題が起きる)
  • ゼロ値のフィールドは省略する
  • 公開構造体に型を埋め込まない(意図せず API を公開してしまう)
  • ゼロ値の構造体にはvarを使う:var user User

スライスとマップ

  • nil スライスを優先する:var t []string(JSON の[]エンコードに限り[]string{}を使う)
  • 境界でコピーする:変更を防ぐためにcopy()またはmaps.Clone()を使う
  • 事前に割り当てる:サイズが分かっている場合はmake([]T, 0, len(input))を使う
  • slicesとmapsパッケージを使う:slices.Sort、slices.Clone、maps.Clone、maps.Equal

Generics(Go 1.18+)

  • 異なる型に対して同一のコードを書く場合に使用します
  • 型安全性のために cmp.Ordered またはカスタム制約を使用します
  • ジェネリック型エイリアス(Go 1.24+):type Set[T comparable] = map[T]struct{}
  • 過度な汎用化は避けます:具体的な型やインターフェースで十分な場合は、それらを使用します
func Filter[T any](s []T, pred func(T) bool) []T {
    result := make([]T, 0, len(s))
    for _, v := range s {
        if pred(v) {
            result = append(result, v)
        }
    }
    return result
}

イテレーター(Go 1.23+)

カスタムイテレーターでは関数を範囲指定して反復処理できます:

func Backward[T any](s []T) func(yield func(int, T) bool) {
    return func(yield func(int, T) bool) {
        for i := len(s) - 1; i >= 0; i-- {
            if !yield(i, s[i]) {
                return
            }
        }
    }
}

for i, v := range Backward(items) {
    fmt.Println(i, v)
}

文字列/バイト列のイテレーター(Go 1.24+):strings.Lines、strings.SplitSeq、strings.SplitAfterSeq


構造化ログ(Go 1.21+)

slog.Info("user created", "id", userID, "email", email)
slog.With("service", "auth").Info("starting")
handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})
  • slog.DiscardHandler(Go 1.24+)を使うと、テストでログを抑制できます
  • キー名に一貫性を持たせ、関連するフィールドを slog.Group でまとめます

パフォーマンス

詳細ガイド:skills/go-performance/SKILL.md | リファレンス:references/performance.md

  • fmt より strconv:fmt.Sprintf("%d", n) ではなく strconv.Itoa(n) を使用します
  • []byte への繰り返し変換を避けます:一度保存して再利用します
  • map の容量を事前確保します:make(map[string]int, len(items))
  • 文字列の連結には Grow() を使う strings.Builder を使用します

テスト

詳細ガイド:skills/go-testing/SKILL.md | リファレンス:references/testing.md

  • テーブル駆動テストでは、サブテストに t.Parallel() を使用します
  • reflect.DeepEqual より go-cmp を使用すると、差分を明確に表示できます
  • 役立つ失敗メッセージ:入力値、実際の値、期待値を含めます
  • セットアップの失敗には t.Fatal を使用します
  • インターフェースは提供側ではなく利用側に置きます
  • T.Context と T.Chdir(Go 1.24+)
  • b.Loop()(Go 1.24+):より簡潔なベンチマークを作成でき、b.ResetTimer() は不要です
  • synctest.Test(Go 1.25+):合成時間を使った決定論的な並行テスト

リソース管理(Go 1.24+)

  • runtime.AddCleanup:オブジェクトごとに複数のクリーンアップを実行でき、循環参照によるリークが発生しません(SetFinalizer の代替)
  • weak.Pointer[T]:キャッシュ、正規化、オブザーバー向けの弱参照
  • os.Root:パス走査攻撃を防ぐ、スコープが限定されたファイルアクセス

パターン

詳細なリファレンス:references/patterns.md

  • 関数型オプション:設定可能なコンストラクターには WithTimeout(d)、WithLogger(l) を使用します
  • インターフェースへの適合性:var _ http.Handler = (*Handler)(nil)
  • クリーンアップには defer:わずかなオーバーヘッドで安全性を高められます
  • グレースフルシャットダウン:シグナル処理と srv.Shutdown(ctx) を組み合わせます
  • 列挙値は 1 から開始:0 は無効/未設定を表します
  • time.Duration を使用します:時間を表す値に生の整数を使用しません
  • 2 値を返す型アサーション:パニックを防ぐために t, ok := i.(string) を使用します
  • コンテキストを最初の引数にします:func Process(ctx context.Context, ...)
  • 変更可能なグローバル変数を避けます:依存性注入を使用します
  • init() を避けます:main で明示的に初期化します
  • //go:embed(Go 1.16+):静的ファイルを埋め込みます
  • フィールドタグ:マーシャリングする構造体には json:"name" を明示します
  • コンテナーを認識した GOMAXPROCS(Go 1.25+):cgroup に基づくチューニングを自動的に行います

よくある落とし穴

詳細なリファレンス:references/gotchas.md

落とし穴対処法
ループ変数のキャプチャ(1.22 未満)Go 1.22+ で修正済み(反復ごとの変数)
defer は引数を即座に評価するクロージャー内でキャプチャします
nil インターフェースと nil ポインターnil を明示的に返します
エラー確認前に結果を使用する必ず先に err を確認します(Go 1.25 で強制)
map の反復順序slices.Sorted(maps.Keys(m)) でキーをソートします
スライスの append で背後の配列が共有される完全スライス式 a[:2:2] を使用します

リント

詳細ガイド:skills/go-linting/SKILL.md

  • 標準のリンター集約ツールとして golangci-lint を使用します
  • 推奨リンター:errcheck、govet、staticcheck、revive、gosimple、goimports、errorlint、bodyclose
  • ツール依存関係として追加します(Go 1.24+):go get -tool github.com/golangci/golangci-lint/cmd/golangci-lint
  • CI で実行します:GitHub Actions では golangci/golangci-lint-action を使用します
  • 抑制は必要最小限にします://nolint コメントを使うより、問題を修正します

プロジェクトの構成

完全なガイド:skills/go-project-layout/SKILL.md

  • cmd/:実行可能ファイルごとにサブディレクトリを作成し、main.go は薄く保ちます
  • internal/:Go ツールチェーンによってアクセスが制限されるプライベートパッケージ
  • pkg/、src/、models/、utils/ は避ける:パッケージ名は目的に沿って付けます
  • フラットな構成で問題ありません:小規模なプロジェクトでは、深いディレクトリ階層は避けます
  • Dockerfile:マルチステージビルドを使い、CGO_ENABLED=0 を設定し、distroless ベースイメージを使用します

セキュリティ

完全なガイド:skills/go-security/SKILL.md

  • パラメーター化 SQL クエリ:ユーザー入力を文字列に埋め込まないでください
  • os.Root(Go 1.24+):パストラバーサルを防ぐ、スコープが限定されたファイルアクセス
  • 境界で検証する:型付き構造体にデコードし、フィールドを検証します
  • シークレットをハードコードしたり、ログに記録したりしない:String() で値を秘匿する Secret 型を使用します
  • 標準の暗号機能のみを使用する:ランダムバイトには crypto/rand、パスワードには bcrypt を使います
  • HTTP タイムアウト:必ず ReadTimeout、WriteTimeout、IdleTimeout を設定します
  • govulncheck:既知の脆弱性がないか、依存関係をスキャンします
  • go test -race:CI では必ず競合検出器を有効にして実行します

実験的機能(Go 1.25)

  • encoding/json/v2:GOEXPERIMENT=jsonv2 で有効にします。パフォーマンスが向上し、ストリーミングと呼び出しごとのカスタムマーシャラーに対応しています。

ドキュメント

  • コメントは完全な文にし、宣言された名前から始めます
  • パッケージコメントは package 宣言の前に置き、間に空行を入れません

参考資料

  1. Google Go スタイルガイド
  2. Uber Go スタイルガイド
  3. Effective Go
  4. Go コードレビューのコメント
  5. Go 1.23 リリースノート
  6. Go 1.24 リリースノート
  7. Go 1.25 リリースノート

コメント