
こんにちは。よっしーです(^^)
本日は、Go言語の言語仕様について解説しています。
背景
Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。
言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。
そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。
言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!
ラベル付き文(Labeled statements)
ラベル付き文は、goto、break、または continue 文のターゲットになることができる。
LabeledStmt = Label ":" Statement .
Label = identifier .
Error: log.Panic("error encountered")
解説
ラベル付き文ってなに?
ラベル付き文は、文に**名前(ラベル)**をつける仕組みです。ラベル名: の形で文の前に書きます。
Error: log.Panic("error encountered")
//^^^ ラベル名
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ラベルが付けられた文
ラベルをつけること自体は文の動作を変えません。goto、break、continue から参照するための「目印」になるだけです。
ラベルの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()
}
実際のところ、ラベルは break と continue で使うのがほぼ唯一の実用的な場面です。
おわりに
本日は、Go言語の言語仕様について解説しました。

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

コメント