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

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

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

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

スポンサーリンク

背景

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

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

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

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

構造体リテラル(Struct literals)

キーなしの構造体リテラルでは、要素リストはフィールドが宣言された順序で各構造体フィールドに対応する要素を含まなければならない。

キーありの構造体リテラルでは、以下のルールが適用される:

  • すべての要素にキーがなければならない。
  • 各キーは構造体型で宣言されたフィールド名でなければならない。
  • 要素リストは各構造体フィールドに対応する要素を持つ必要はない。省略されたフィールドは、そのフィールドのゼロ値を得る。
  • 異なるパッケージに属する構造体のエクスポートされていないフィールドに対して要素を指定するとエラーとなる。

以下の宣言が与えられたとき

type Point3D struct { x, y, z float64 }
type Line struct { p, q Point3D }

次のように書くことができる

origin := Point3D{}                            // Point3D のゼロ値
line := Line{origin, Point3D{y: -4, z: 12.3}}  // line.q.x はゼロ値

解説

キーなしとキーあり、2つの書き方

構造体リテラルには2つのスタイルがあります。それぞれルールが異なるので、分けて見ていきましょう。

type Point3D struct { x, y, z float64 }

// キーなし:すべてのフィールドを宣言順に書く
p1 := Point3D{1, 2, 3}       // x=1, y=2, z=3

// キーあり:フィールド名を指定して書く
p2 := Point3D{x: 1, y: 2, z: 3}

キーなしの制約:「全部書く・順番通り」

キーなしの場合、フィールドの数と順番がぴったり一致していないとコンパイルエラーになります。

type Point3D struct { x, y, z float64 }

p := Point3D{1, 2}        // エラー! z が足りない
p := Point3D{1, 2, 3, 4}  // エラー! 多すぎる

フィールドが少ないうちはいいですが、フィールドが増えてくると「3番目って何だっけ?」と混乱しがちです。

キーありの自由度:「好きなものだけ・順不同」

キーありの場合は、ずっと柔軟です。

// 一部のフィールドだけ指定できる(残りはゼロ値)
p := Point3D{y: -4, z: 12.3}  // x は 0.0 になる

// 順番も自由
p := Point3D{z: 3, x: 1, y: 2}  // OK!

ただし「キーありとキーなしを混ぜる」ことはできません。

p := Point3D{1, y: 2, 3}  // エラー! 混在はダメ

キーありが推奨される理由

実際の開発では、キーありの書き方が圧倒的におすすめです。理由は3つあります。

  1. 読みやすい:どのフィールドに何を入れているか一目でわかる
  2. 安全:フィールドの順番が変わっても壊れない
  3. 省略できる:不要なフィールドを書かなくてよい
// キーなし:何が何だかわかりにくい
user := User{"Alice", 30, true, "tokyo", "alice@example.com"}

// キーあり:意味が明確
user := User{
    Name:  "Alice",
    Age:   30,
    Email: "alice@example.com",
    // Active や City は省略 → ゼロ値になる
}

他パッケージの非公開フィールドには触れない

Go では小文字で始まるフィールドはエクスポートされません(パッケージ外から見えません)。そのため、他のパッケージの構造体をリテラルで作るとき、非公開フィールドに値を指定するとエラーになります。

// 仮に別パッケージに以下の型があるとする
// type point struct { X, y float64 }  // X は公開、y は非公開

p := other.Point{X: 1, y: 2}  // エラー! y は非公開フィールド

これは逆に言うと、キーなしの書き方は他パッケージの構造体には基本的に使えないことを意味します。すべてのフィールドを書く必要があるのに、非公開フィールドには触れないからです。これもキーありが推奨される理由のひとつですね。

入れ子の構造体リテラル

原文の Line の例は、構造体の中に構造体が入っている(入れ子の)ケースです。

type Point3D struct { x, y, z float64 }
type Line struct { p, q Point3D }

origin := Point3D{}                             // {0, 0, 0}
line := Line{origin, Point3D{y: -4, z: 12.3}}   // キーなしで p と q を指定

Line のリテラルはキーなしなので、1番目の要素が p、2番目が q に対応します。Point3D{y: -4, z: 12.3} はキーありなので、x は省略されてゼロ値(0.0)になります。

キーありで書くとこうなります。

line := Line{
    p: origin,
    q: Point3D{y: -4, z: 12.3},
}

こちらのほうが、どのフィールドに何を入れているかが明確ですね。

おわりに 

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

よっしー
よっしー

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

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

コメント

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