Go言語入門:言語仕様 -Vol.103-

スポンサーリンク
Go言語入門:言語仕様 -Vol.103- 用語解説
Go言語入門:言語仕様 -Vol.103-
この記事は約5分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

本日は、Go言語の言語仕様について解説しています。

スポンサーリンク

背景

Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。

言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。

そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。

言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!

ラベル付き文(Labeled statements)

ラベル付き文は、gotobreak、または continue 文のターゲットになることができる。

LabeledStmt = Label ":" Statement .
Label       = identifier .
Error: log.Panic("error encountered")

解説

ラベル付き文ってなに?

ラベル付き文は、文に**名前(ラベル)**をつける仕組みです。ラベル名: の形で文の前に書きます。

Error: log.Panic("error encountered")
//^^^  ラベル名
//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ラベルが付けられた文

ラベルをつけること自体は文の動作を変えません。gotobreakcontinue から参照するための「目印」になるだけです。

ラベルの3つの使い方

1. goto のジャンプ先

func example() {
    fmt.Println("start")
    goto end
    fmt.Println("skipped")  // ここは実行されない
end:
    fmt.Println("end")
}

goto は直接そのラベルにジャンプします。ただし Go では goto の使用は推奨されず、使える場面も制限されています。

2. break でネストしたループから抜ける

これがラベルの最も実用的な使い方です。

outer:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            if i*j > 20 {
                break outer  // 外側のループごと抜ける
            }
        }
    }

ラベルなしの break は一番内側のループしか抜けられません。外側のループを一気に抜けたいときにラベルが必要になります。

// ラベルなしの break → 内側のループだけ抜ける
for i := 0; i < 10; i++ {
    for j := 0; j < 10; j++ {
        if condition {
            break  // 内側の for を抜けるだけ。外側は続く
        }
    }
}

3. continue で外側のループの次の反復へ

outer:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            if shouldSkip(i, j) {
                continue outer  // 外側のループの次の i へ進む
            }
            process(i, j)
        }
    }

continue outer は内側のループを中断し、外側のループの次の反復(次の i)に進みます。

ラベルのスコープ

ラベルは、それが宣言された関数の中でだけ有効です。関数の外からは参照できません。また、同じ関数内で同じ名前のラベルを2回宣言するとコンパイルエラーになります。

func f() {
    loop:
        for { break loop }

    loop:  // コンパイルエラー! 同じ関数内でラベル名が重複
        for { break loop }
}

goto を避けるべき理由

Go には goto がありますが、ほとんどの場合、使わないほうがよいです。コードの流れが追いにくくなり、バグの原因になります。

goto が許容されるまれなケースは、エラー処理で複数の場所からクリーンアップ処理にジャンプしたいときなどですが、defer を使えば同じことがよりきれいに書けます。

// goto を使う(非推奨)
func process() error {
    resource := acquire()
    if err := step1(); err != nil {
        goto cleanup
    }
    if err := step2(); err != nil {
        goto cleanup
    }
    return nil
cleanup:
    release(resource)
    return err
}

// defer を使う(推奨)
func process() error {
    resource := acquire()
    defer release(resource)
    if err := step1(); err != nil {
        return err
    }
    return step2()
}

実際のところ、ラベルは breakcontinue で使うのがほぼ唯一の実用的な場面です。

おわりに 

本日は、Go言語の言語仕様について解説しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました