mcpField
G
golang-master

golang-master

github.com/tomlord1122開発047 回インストール6 週間前に更新
リポジトリ

golang-master について

Go 開発者向けのコーディングスキルです。慣用的な設計、並行処理、エラー処理、テスト、性能分析を扱い、リンターとベンチマーク用スクリプトも含みます。

主な機能

  1. 01Go の問題分類
  2. 02慣用的な設計指針
  3. 03並行処理パターン
  4. 04エラー処理の方針
  5. 05テストと性能分析の指針
  6. 06リンターとベンチマーク用スクリプト

活用シーン

  1. 01goroutine の連携設計
  2. 02エラーの追跡とラップ
  3. 03テーブル駆動テストの計画
  4. 04プロジェクトの lint 実行

インストール

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

$npx skills add https://github.com/tomlord1122/tomtom-skill --skill golang-master

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

同梱ファイルscripts/benchmark.shscripts/lint.sh

詳細

Go 言語エキスパート

並行処理パターン、パフォーマンス最適化、標準ライブラリの使用方法、テスト戦略など、Go 言語を極めるためのエキスパートアシスタントです。

思考プロセス

起動したら、Go 関連の問題を解決するために、次の構造化された思考アプローチに従います。

ステップ 1:問題の分類

目標: どのような種類の Go の課題かを把握します。

確認すべき主な質問:

  • 並行処理の問題ですか?(goroutine、チャネル、競合状態)
  • パフォーマンスの問題ですか?(メモリ、CPU、アロケーション)
  • 設計の問題ですか?(インターフェース、構造体の合成、パッケージ)
  • デバッグの問題ですか?(エラーの追跡、予期しない動作)
  • テストの問題ですか?(ユニットテスト、ベンチマーク、モック)

判断ポイント: 問題を分類し、適切なパターンを選択します。

  • 並行処理 → 競合状態と適切な同期を確認する
  • パフォーマンス → まずプロファイルを取り、その後最適化する
  • 設計 → インターフェース分離と、継承より合成を優先する
  • デバッグ → エラーチェーンを追跡し、nil の扱いを確認する
  • テスト → テーブル駆動テスト、依存性注入
ステップ 2:コンテキストの分析

目標: 既存のコードベースのコンテキストと制約を把握します。

確認すべき主な質問:

  • 使用している Go のバージョンは何ですか?(ジェネリクスには 1.18 以降が必要です)
  • モジュール構成はどうなっていますか?(標準的なレイアウトか、フラットか)
  • どのような依存関係がありますか?(標準ライブラリか、サードパーティ製か)
  • 既存のパターンに従う必要がありますか?(エラー処理のスタイル、ロギングの方法)

実施事項:

  1. go.mod で Go のバージョンと依存関係を確認する
  2. 既存のコードを調べ、確立されたパターンを確認する
  3. プロジェクト固有の規約を特定する
ステップ 3:ソリューションの設計(Go らしい設計)

目標: Go のベストプラクティスに従ったソリューションを設計します。

思考の枠組み - 以下の原則を適用します:

  1. シンプルさを最優先

    • 「これを実現する、もっとシンプルな方法はありますか?」
    • 過剰な設計を避けます。Go では明示性が重視されます
  2. エラー処理

    • 「ここで失敗する可能性はありますか?失敗をどのように伝播させるべきですか?」
    • ラップには fmt.Errorf("context: %w", err) を使用する
    • ドメイン固有のエラーにはカスタムエラー型を定義する
  3. 並行処理の安全性

    • 「このデータは複数の goroutine からアクセスされますか?」
    • 「ミューテックス、チャネル、アトミック操作のどれが必要ですか?」
    • 調整にはチャネルを、状態の保護にはミューテックスを優先する
  4. インターフェース設計

    • 「必要なのはどのような振る舞いですか?どのようなデータですか?」ではありません
    • インターフェースは小さく保つ(メソッド 1~3 個)
    • インターフェースを受け取り、具体型を返す
  5. リソース管理

    • 「閉じる、またはクリーンアップする必要があるものは何ですか?」
    • クリーンアップには defer を使用する
    • キャンセルのためにコンテキストを伝播させる
ステップ 4:パターンを用いた実装

目標: よく知られた Go のパターンを適切に適用します。

パターン選択ガイド:

問題の種類推奨パターン
N 個の項目を並行処理するワーカープール
並行操作を制限するセマフォ
長時間の操作にタイムアウトを設定するDeadline 付きコンテキスト
複数の goroutine を調整するWaitGroup
ファンアウト/ファンイン処理チャネルパイプライン
グレースフルシャットダウンコンテキストのキャンセル + シグナル処理

判断ポイント: 各パターンについて、次の点を確認します。

  • 「この問題にこのパターンが適している理由は何ですか?」
  • 「どのようなエッジケースに対処する必要がありますか?」
ステップ 5:テスト戦略

目標: コードの正確性と保守性を確保します。

思考の枠組み:

  • 「テストすべき正常系は何ですか?」
  • 「どのようなエッジケースで問題が起きる可能性がありますか?」
  • 「このコードはテスト可能ですか?そうでない場合、どのようにリファクタリングすべきですか?」

テストのチェックリスト:

  1. 複数の入力パターンがある関数にはテーブル駆動テストを使用する
  2. 並行処理コードでは競合状態を検出する(go test -race)
  3. パフォーマンスが重要なコードにはベンチマークを使用する
  4. 外部依存関係にはモックインターフェースを使用する
ステップ 6:レビューと改善

目標: ソリューションが本番環境で使用できる状態であることを確認します。

最終確認:

  • すべてのエラーを処理するか、コメントで明示的に無視している
  • 呼び出しチェーン全体でコンテキストが伝播している
  • リソースが適切にクローズされている(defer、Close())
  • ゴルーチンリークがない(チャネルがクローズされ、コンテキストがキャンセルされている)
  • コードがテスト可能である(依存関係が注入されている)
  • エクスポートされたシンボルのドキュメントがある

使用方法

リンターを実行する
bash /mnt/skills/user/golang-master/scripts/lint.sh [project-dir] [fix-mode]

引数:

  • project-dir - プロジェクトディレクトリ(デフォルト:現在のディレクトリ)
  • fix-mode - 問題を自動修正するには true に設定します(デフォルト:false)

例:

bash /mnt/skills/user/golang-master/scripts/lint.sh
bash /mnt/skills/user/golang-master/scripts/lint.sh ./my-project true

実行内容: go vet、gofmt、staticcheck、golangci-lint、go mod tidy

ベンチマークを実行する
bash /mnt/skills/user/golang-master/scripts/benchmark.sh [project-dir] [pattern] [profile-type]

引数:

  • project-dir - プロジェクトディレクトリ(デフォルト:現在のディレクトリ)
  • pattern - 一致させるベンチマークパターン(デフォルト:.)
  • profile-type - プロファイリング:none、cpu、mem、all(デフォルト:none)

例:

bash /mnt/skills/user/golang-master/scripts/benchmark.sh
bash /mnt/skills/user/golang-master/scripts/benchmark.sh . BenchmarkProcess cpu
bash /mnt/skills/user/golang-master/scripts/benchmark.sh ./myproject . all

ドキュメントリソース

公式ドキュメント:

  • Go ドキュメント:https://go.dev/doc/
  • Effective Go:https://go.dev/doc/effective_go
  • Go by Example:https://gobyexample.com/
  • uber-go/guide:https://github.com/uber-go/guide

並行処理パターン

ワーカープール
func workerPool(jobs <-chan Job, numWorkers int) <-chan Result {
    results := make(chan Result, len(jobs))
    var wg sync.WaitGroup

    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for job := range jobs {
                results <- process(job)
            }
        }()
    }

    go func() {
        wg.Wait()
        close(results)
    }()

    return results
}
タイムアウト付きコンテキスト
func fetchWithTimeout(url string) ([]byte, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
    if err != nil {
        return nil, err
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    return io.ReadAll(resp.Body)
}
セマフォパターン
type Semaphore struct {
    sem chan struct{}
}

func NewSemaphore(n int) *Semaphore {
    return &Semaphore{sem: make(chan struct{}, n)}
}

func (s *Semaphore) Acquire() { s.sem <- struct{}{} }
func (s *Semaphore) Release() { <-s.sem }

エラー処理

エラーのラップ
func processUser(id int) error {
    user, err := fetchUser(id)
    if err != nil {
        return fmt.Errorf("failed to fetch user %d: %w", id, err)
    }

    if err := validateUser(user); err != nil {
        return fmt.Errorf("validation failed for user %d: %w", id, err)
    }

    return nil
}
カスタムエラー型
type NotFoundError struct {
    Resource string
    ID       string
}

func (e *NotFoundError) Error() string {
    return fmt.Sprintf("%s not found: %s", e.Resource, e.ID)
}

// Usage
if errors.Is(err, &NotFoundError{}) {
    // Handle not found
}
エラーの確認
// Use errors.Is for sentinel errors
if errors.Is(err, sql.ErrNoRows) {
    return nil, &NotFoundError{Resource: "user", ID: id}
}

// Use errors.As for error types
var netErr *net.OpError
if errors.As(err, &netErr) {
    // Handle network error
}

パフォーマンスプロファイリング

CPU プロファイリング
# Run benchmark with CPU profile
go test -cpuprofile=cpu.prof -bench=.
go tool pprof cpu.prof

# Interactive commands
(pprof) top10
(pprof) web
(pprof) list FunctionName
メモリプロファイリング
# Run benchmark with memory profile
go test -memprofile=mem.prof -bench=.
go tool pprof -alloc_space mem.prof

# Check for allocations
go build -gcflags='-m' ./...
ベンチマークの例
func BenchmarkProcess(b *testing.B) {
    data := setupTestData()
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        process(data)
    }
}

func BenchmarkProcessParallel(b *testing.B) {
    data := setupTestData()
    b.ResetTimer()

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            process(data)
        }
    })
}

テストパターン

テーブル駆動テスト
func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive", 2, 3, 5},
        {"negative", -1, -2, -3},
        {"zero", 0, 0, 0},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Add(%d, %d) = %d; want %d",
                    tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

ユーザーに結果を提示する

Go のソリューションを提供する場合:

  • Go らしいパターンを使用します
  • 必ずエラーを明示的に処理します
  • コンテキストの伝播を含めます
  • テスト例を提示します
  • Go のバージョン要件を明記します(ジェネリクス:1.18 以降)

トラブルシューティング

「データ競合が検出されました」

  • go test -race を使用して競合を見つけます
  • ミューテックスで共有状態を保護します
  • 通信にはチャネルの使用を検討します

「ゴルーチンリーク」

  • チャネルがクローズされていることを確認します
  • キャンセルにはコンテキストを使用します
  • ブロッキング操作を確認します

「メモリ使用量が多い」

  • pprof でプロファイリングします
  • スライスの容量に関する問題を確認します
  • マップの蓄積がないか確認します

コメント