masalibの日記

システム開発、運用と猫の写真ブログです

golang の入門 structリテラル

go tourでわからなかったことのメモです

go-tour-jp.appspot.com

package main

import "fmt"

type Vertex struct {
    X, Y int
}

var (
    v1 = Vertex{1, 2}  // has type Vertex
    v2 = Vertex{X: 1}  // Y:0 is implicit
    v3 = Vertex{}      // X:0 and Y:0
    p  = &Vertex{1, 2} // has type *Vertex
)

func main() {
    fmt.Println(v1, p, v2, v3)
}

なんとなくは理解できたのですがわからないので調べた。

&Vertex{1, 2} の部分について

この部分はGo言語におけるポインタの使用に関するものです。具体的には、&Vertex{1, 2}Vertex 構造体のインスタンスを作成し、そのポインタを返します。

以下に詳細を説明します:

Vertex構造体

まず、Vertex 構造体は以下のように定義されています:

type Vertex struct {
    X, Y int
}

構造体の初期化

Vertex 構造体のインスタンスを作成するには以下のようにします:

v := Vertex{1, 2}

これは、X フィールドに 1Y フィールドに 2 を持つ Vertex 構造体のインスタンスを作成します。

ポインタの取得

ここで、& 演算子を使うことで、Vertex 構造体のインスタンスのポインタを取得できます:

p := &Vertex{1, 2}

このコードは、Vertex 構造体のインスタンスを作成し、そのメモリ上のアドレス(ポインタ)を変数 p に格納します。p の型は *Vertex となります。

ポインタの利用

ポインタを使うことで、構造体のフィールドに対して間接的にアクセスすることができます。例えば:

p := &Vertex{1, 2}
fmt.Println(p.X, p.Y) // 1 2 と表示される

ここで、p.Xp.Y にアクセスすることで、ポインタを経由して Vertex 構造体のフィールドにアクセスしています。

プログラムの動作

質問にあるプログラムの main 関数では、以下のようにしています:

func main() {
    fmt.Println(v1, v2, v3)
    fmt.Println(p)
}
  • v1, v2, v3 はそれぞれ異なる方法で初期化された Vertex 構造体のインスタンスです。
  • pVertex 構造体のポインタです。

このプログラムを実行すると、構造体インスタンスの内容とポインタが表示されます:

{1 2} {1 0} {0 0}
&{1 2}

最初の Println では v1, v2, v3 の値が表示され、次の Println ではポインタ p が指す Vertex 構造体の内容が表示されます(ポインタであることを示す & が付いています)。

間接的に操作する例

以下の例では、Vertex 構造体のフィールドをポインタを通じて変更する方法を示しています。

package main

import "fmt"

type Vertex struct {
    X, Y int
}

// 関数 updateVertex でポインタを受け取り、フィールドを更新します
func updateVertex(v *Vertex, newX int, newY int) {
    v.X = newX
    v.Y = newY
}

func main() {
    // Vertex構造体のポインタを作成
    p := &Vertex{1, 2}

    // 初期値を表示
    fmt.Println("Before update:", *p)

    // ポインタを使って構造体のフィールドを更新
    updateVertex(p, 10, 20)

    // 更新後の値を表示
    fmt.Println("After update:", *p)
}

このプログラムの出力は以下のようになります:

Before update: {1 2}
After update: {10 20}

説明

  1. 構造体のポインタを作成: go p := &Vertex{1, 2} これは、X1Y2 である Vertex 構造体のポインタを作成します。

  2. 初期値を表示: go fmt.Println("Before update:", *p) *p を使うことでポインタ p が指す構造体の値を取得し、初期値 {1 2} が表示されます。

  3. 関数 updateVertex でフィールドを更新: go updateVertex(p, 10, 20) この関数は、ポインタ p を受け取り、X フィールドを 10 に、Y フィールドを 20 に更新します。

  4. 更新後の値を表示: go fmt.Println("After update:", *p) 再び *p を使って更新後の構造体の値を表示します。この時点で、X10Y20 になっています。

このように、ポインタを使うことで構造体のフィールドを間接的に操作できます。 ポインタを関数に渡すことで、関数内で構造体の内容を変更できる点が重要です。