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

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

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

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

スポンサーリンク

背景

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

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

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

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

終端文(Terminating statements)

終端文は、ブロック内の通常の制御フローを中断する。以下の文が終端文である:

  1. return 文または goto 文。
  2. 組み込み関数 panic の呼び出し。
  3. 文リストが終端文で終わるブロック。
  4. 以下の条件を満たす if 文:
    • else 分岐が存在し、かつ
    • 両方の分岐が終端文である。
  5. 以下の条件を満たす for 文:
    • その for 文を参照する break 文がなく、かつ
    • ループ条件が存在せず、かつ
    • その for 文が range 節を使用していない。
  6. 以下の条件を満たす switch 文:
    • その switch 文を参照する break 文がなく、
    • default ケースがあり、かつ
    • default を含む各ケースの文リストが、終端文またはラベル付きの場合もある fallthrough 文で終わる。
  7. 以下の条件を満たす select 文:
    • その select 文を参照する break 文がなく、かつ
    • default が存在する場合はそれを含む各ケースの文リストが終端文で終わる。
  8. 終端文にラベルを付けたラベル付き文。

その他のすべての文は終端文ではない。

文リストが空でなく、その最後の空でない文が終端文である場合、その文リストは終端文で終わる。


解説

終端文ってなに?

終端文とは、「この先には進まない」とコンパイラが判断できる文のことです。

なぜこの概念が必要かというと、関数宣言の節で学んだように、戻り値を宣言した関数は必ず return で終わらなければならないからです。コンパイラは終端文の定義を使って、「すべてのパスが正しく終了するか」をチェックしています。

func abs(x int) int {
    if x >= 0 {
        return x
    } else {
        return -x
    }
    // ここに到達しないことをコンパイラは理解している
    // → if 文が終端文なので OK
}

基本的な終端文

最もシンプルな終端文は returngotopanic です。

func f() int {
    return 42      // 終端文 ✅
}

func g() int {
    panic("error") // 終端文 ✅(この先には進まない)
}

if 文が終端文になる条件

if 文が終端文になるには、else があり、かつ両方の分岐が終端文でなければなりません。

// ✅ 終端文:else があり、両方が return で終わる
func sign(x int) string {
    if x > 0 {
        return "positive"
    } else {
        return "non-positive"
    }
}

// ❌ 終端文ではない:else がない
func bad(x int) string {
    if x > 0 {
        return "positive"
    }
    // else がないので、ここに到達する可能性がある
    // → この後に return が必要
}

else がない if は、条件が false のとき次の行に進むので、制御フローを完全には止められません。

for 文が終端文になる条件

条件なしの for は無限ループなので、終端文になります。ただし break があると脱出できてしまうのでダメです。

// ✅ 終端文:条件なし、break なし、range なし
func forever() {
    for {
        doSomething()
    }
    // この行には到達しない
}

// ❌ 終端文ではない:break がある
func notTerminating() int {
    for {
        if condition {
            break  // ループを抜けられる → 終端文ではない
        }
    }
    return 0  // ← これが必要
}

// ❌ 終端文ではない:条件がある
func loop() {
    for x > 0 {  // 条件が false になるとループを抜ける
        x--
    }
}

switch 文が終端文になる条件

switch が終端文になるには3つの条件をすべて満たす必要があります。

// ✅ 終端文:default あり、全ケースが return で終わる、break なし
func describe(x int) string {
    switch {
    case x > 0:
        return "positive"
    case x < 0:
        return "negative"
    default:
        return "zero"
    }
}

// ❌ 終端文ではない:default がない
func incomplete(x int) string {
    switch {
    case x > 0:
        return "positive"
    case x < 0:
        return "negative"
    }
    // x == 0 のケースがない → default が必要
    return "zero"  // ← これが必要
}

実用的な理解:コンパイラの視点

終端文のルールは、コンパイラが「この関数は必ず値を返す」と確信できるかどうかの判定基準です。

func example(x int) int {
    if x > 0 {
        return 1
    }
    // コンパイラ:「x <= 0 のときどうするの?」
    // → コンパイルエラー:missing return
}

よくある解決パターンは3つです。

// パターン1:else を追加する
func f(x int) int {
    if x > 0 {
        return 1
    } else {
        return -1
    }
}

// パターン2:関数の最後に return を置く
func f(x int) int {
    if x > 0 {
        return 1
    }
    return -1  // すべてのパスをカバー
}

// パターン3:switch の default を使う
func f(x int) int {
    switch {
    case x > 0:
        return 1
    default:
        return -1
    }
}

パターン2は Go で最もよく使われるスタイルです。else を使わず、早期リターンで正常系を先に処理し、最後にデフォルトケースを置くのが Go らしい書き方ですね。

再帰的な定義

終端文の定義は再帰的であることに注目してください。たとえば「ブロックが終端文で終わる」→「そのブロック自体が終端文」→「そのブロックを含む if 文が終端文になりうる」というように、入れ子で判定が進みます。

func f(x int) int {
    if x > 0 {
        {  // ブロック
            fmt.Println(x)
            return x  // ← このブロックの最後が終端文
        }  // → このブロック自体が終端文
    } else {
        return -x
    }  // → if 文全体が終端文
}  // → 関数は正しく終端している

おわりに 

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

よっしー
よっしー

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

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

コメント

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