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

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

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

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

スポンサーリンク

背景

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

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

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

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

if文(If statements)

if 文は、真偽値式の値に応じて2つの分岐の条件付き実行を指定する。式が true と評価された場合、if 分岐が実行される。そうでなければ、存在する場合は else 分岐が実行される。

IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
if x > max {
	x = max
}

式の前に単純文を置くことができ、それは式が評価される前に実行される。

if x := f(); x < y {
	return x
} else if x > z {
	return z
} else {
	return y
}

解説

if文の基本

Go の if 文は他の言語と似ていますが、条件式に括弧が不要で、波括弧が必須という特徴があります。

// Go の if(括弧なし、波括弧必須)
if x > 0 {
    fmt.Println("positive")
}

// C や Java の if(括弧あり、波括弧は省略可能)
// if (x > 0) fmt.Println("positive")  ← Go ではエラー

if-else と if-else if

if x > 0 {
    fmt.Println("positive")
} else if x < 0 {
    fmt.Println("negative")
} else {
    fmt.Println("zero")
}

elseif の閉じ波括弧 }同じ行に書かなければなりません。これは Go のセミコロン自動挿入ルールのためです。

// ❌ コンパイルエラー!
if x > 0 {
    fmt.Println("positive")
}
else {  // } の後に改行があるとセミコロンが挿入されてしまう
    fmt.Println("non-positive")
}

// ✅ 正しい書き方
if x > 0 {
    fmt.Println("positive")
} else {
    fmt.Println("non-positive")
}

初期化文つき if

Go の if には、条件式の前に単純文を1つ書けるという独自の機能があります。

if x := f(); x < y {
    return x
}

これは以下と同じ意味です。

x := f()
if x < y {
    return x
}

ただし、大きな違いがあります。初期化文で宣言した変数のスコープが if 文全体(else 分岐も含む)に限定されるのです。

if x := f(); x < y {
    fmt.Println(x)   // ✅ ここでは x が使える
} else {
    fmt.Println(x)   // ✅ else でも x が使える
}
fmt.Println(x)       // ❌ コンパイルエラー! if の外では x は見えない

エラーハンドリングでの活用

初期化文つき if は、Go のエラーハンドリングで最もよく使われるパターンです。

if err := doSomething(); err != nil {
    return err
}
// err はここでは見えない → 名前空間が汚れない

もし初期化文がなかったら、err が関数全体にスコープを持ってしまいます。

err := doSomething()
if err != nil {
    return err
}
// err がまだ見えている → 後で別の err と混同する危険

複数のエラーチェックが続く場面で、この違いが効いてきます。

if err := step1(); err != nil {
    return err
}
if err := step2(); err != nil {  // 別の err。前の err とは別物
    return err
}
if err := step3(); err != nil {
    return err
}

errif のスコープに閉じているので、変数名の衝突を気にせずに同じ名前を使い回せます。

Go のスタイル:else を避ける

Go のコミュニティでは、else をなるべく使わず早期リターンで書くスタイルが好まれます。

// Go らしくない書き方
func process(x int) string {
    if x > 0 {
        return "positive"
    } else {
        return "non-positive"
    }
}

// Go らしい書き方
func process(x int) string {
    if x > 0 {
        return "positive"
    }
    return "non-positive"
}

早期リターンを使うと、ネストが浅くなりコードが読みやすくなります。特にエラーハンドリングでは、「異常系を先に処理して早めに抜け、正常系をメインの流れに置く」のが Go の定番です。

func readFile(name string) ([]byte, error) {
    f, err := os.Open(name)
    if err != nil {
        return nil, err  // 異常系:早期リターン
    }
    defer f.Close()

    data, err := io.ReadAll(f)
    if err != nil {
        return nil, err  // 異常系:早期リターン
    }

    return data, nil     // 正常系:メインの流れ
}

おわりに 

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

よっしー
よっしー

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

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

コメント

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