mcpField
G
go-control-flow

go-control-flow

github.com/cxuu開発1861.2k 回インストール19 週間前に更新
リポジトリ

go-control-flow について

Go の制御フロー、変数スコープ、ループ、switch、ブランク識別子を扱うコーディングスキルです。一般的な Go の書き方を適用し、スコープや制御フローの誤りを避ける開発者向けです。

主な機能

  1. 01条件文の初期化とスコープ
  2. 02ガード節と早期リターン
  3. 03短縮宣言とシャドーイング
  4. 04for と range の規則
  5. 05switch の脱出とブランク識別子

活用シーン

  1. 01if や switch 内に変数を限定
  2. 02短縮宣言のシャドーイング確認
  3. 03map や文字列の反復処理

インストール

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

$npx skills add https://github.com/cxuu/golang-skills --skill go-control-flow

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

同梱ファイルreferences/BLANK-IDENTIFIER.mdreferences/SWITCH-PATTERNS.md

詳細

Go の制御フロー

リソースのルーティング

  • references/SWITCH-PATTERNS.md - switch 文、型 switch、fallthrough、ラベル付き break を使用する場合に読みます。
  • references/BLANK-IDENTIFIER.md - _、空 import、未使用のコンパイル時アサーション、意図的な破棄を使用する場合に読みます。

初期化文付きの if

if と switch は、省略可能な初期化文を受け取ります。これを使って、変数のスコープを条件ブロック内に限定します。

if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}

if の後の数行を超えて変数を使う必要がある場合は、変数を別途宣言し、通常の if を使います。

x, err := f()
if err != nil {
    return err
}
// lots of code that uses x

エラー時のインデント(ガード節)

if 本体の末尾が break、continue、goto、または return の場合は、不要な else を省略します。成功時の処理はインデントせずに記述します。

f, err := os.Open(name)
if err != nil {
    return err
}
d, err := f.Stat()
if err != nil {
    f.Close()
    return err
}
codeUsing(f, d)

if がすでに return している場合に、通常の処理を else の中に入れてはいけません。


再宣言と再代入

:= による短縮宣言では、同じスコープ内の変数を再宣言できます。

f, err := os.Open(name)  // declares f and err
d, err := f.Stat()       // declares d, reassigns err

変数 v は、すでに宣言されている場合でも、次の条件を満たせば := 宣言に含められます。

  1. 宣言が既存の v と同じスコープ内にある
  2. 値を v に代入できる
  3. 宣言によって、少なくとももう1つの変数が新たに作成される
変数のシャドーイング

警告:v が外側のスコープで宣言されている場合、:= はそれをシャドーイングする新しい変数を作成します。これはよくあるバグの原因です。

// Bug: ctx inside the if block shadows the outer ctx
if *shortenDeadlines {
    ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
    defer cancel()
}
// ctx here is still the original — the shadowed ctx didn't escape

// Fix: use = instead of :=
var cancel func()
ctx, cancel = context.WithTimeout(ctx, 3*time.Second)

for ループ

Go で使えるループ構文は for だけです。while、do-while、C スタイルの for を統合しています。

// Condition-only (Go's "while")
for x > 0 {
    x = process(x)
}

// Infinite loop
for {
    if done() { break }
}

// C-style three-component
for i := 0; i < n; i++ { ... }
range

range はスライス、マップ、文字列、チャネルを反復処理します。

for i, v := range slice { ... }   // index + value
for k, v := range myMap { ... }   // key + value (non-deterministic order)
for i, r := range "héllo" { ... } // byte index + rune (not byte)
for v := range ch { ... }         // receives until channel closed

主なルール:

  • 文字列に対する range はバイトではなくルーンを返します。i はバイトオフセットです
  • マップに対する range の順序は非決定的です。順序に依存しないでください
  • インデックスまたは値を破棄するには _ を使います:for _, v := range slice
並行代入

Go にカンマ演算子はありません。複数のループ変数には並行代入を使います。

for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}

++ と -- は式ではなく文です。並行代入では使用できません。


switch:ラベル付き break

for ループ内の switch にある break は、switch だけを抜けます。外側のループを抜けるには、ラベル付き break を使います。

Loop:
    for _, v := range items {
        switch v.Type {
        case "done":
            break Loop  // breaks the for loop
        }
    }

型 switch については、go-interfaces:型 switch を参照してください。


空識別子

エラーを安易に破棄してはいけません。その後に nil 参照によるパニックが発生する可能性があります。

コンパイル時のインターフェースアサーションは、go-interfaces に振り分けてください。


クイックリファレンス

パターンGo の慣用形
初期化文付き ifif err := f(); err != nil { }
早期 returnif 本体が return する場合は else を省略
再宣言同じスコープ + 新しい変数がある場合、:= は再代入する
シャドーイングの落とし穴内側のスコープの := は新しい変数を作成する
並行代入i, j = i+1, j-1
式なし switchswitch { case cond: }
カンマ区切りの casecase 'a', 'b', 'c':
fallthrough なしデフォルトの動作(必要な場合は明示的に fallthrough)
switch 内のループを抜けるbreak Label
値を破棄する_, err := f()
副作用目的の importimport _ "pkg"
インターフェースの確認go-interfaces に振り分ける

関連スキル

  • エラーフロー:ガード節、早期 return、またはエラー優先のパターンを構成する場合は、go-error-handling を参照してください
  • 型 switch:型 switch、comma-ok イディオム、またはインターフェースの充足確認を使用する場合は、go-interfaces を参照してください
  • ネストの削減:ネストの深さを減らす場合や、書式に関する疑問を解決する場合は、go-style-core を参照してください
  • 変数のスコープ:if-init、:= による再宣言、または変数スコープの縮小を行う場合は、go-declarations を参照してください

コメント