Goでは、structは_フィールド_と呼ばれる名前付きの要素を並べたものです。各フィールドは名前と型を持ちます。
フィールドの名前は、structの中で一意でなければなりません。
structは、オブジェクト指向プログラミングのパラダイムにおける_クラス_と比べることができます。
新しいstructは、typeとstructというキーワードを使って作成し、フィールドの名前と型を明示的に定義します。
たとえば、ここでは図形の名前とサイズを保持するShapeというstructを定義します。
type Shape struct {
name string
size int
}
structのフィールド名はGoの慣習に従います。名前が小文字で始まるフィールドは同じパッケージ内のコードからしか見えませんが、大文字で始まるフィールドは他のパッケージからも見えます。
structを定義したら、フィールド名を使って、どの順番でもよいのでフィールドを指定し、新しいインスタンスを作成します。
s := Shape {
name: "Square",
size: 25,
}
インスタンスのフィールドを読み取ったり変更したりするには、.記法を使います。
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
初期値が代入されていないフィールドは、ゼロ値になります。 たとえば、次のようになります。
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
フィールドを_順番どおり_に定義するなら、フィールド名を使わずにstructのインスタンスを作成できます。
s := Shape {
"Oval",
20,
}
ただし、この構文は_壊れやすいコード_と見なされます。フィールドが追加されたときに壊れる可能性があるからです。特に、新しいフィールドが別の型である場合にそうなります。
次の例では、Shapeにフィールドを1つ追加します。
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
structのインスタンスを作成するのを助けてくれる関数があると、便利なことがあります。
慣習として、こうした関数は通常Newと呼ばれるか、名前がNewで始まります。ただし、これらはただの普通の関数なので、好きな名前を付けてかまいません。
他の言語のコンストラクターを思い起こさせるかもしれませんが、Goではこれらはただの普通の関数です。
次の例では、こうしたNew関数の1つを使ってShapeの新しいインスタンスを作成し、図形のsizeにデフォルト値を自動的に設定しています。
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
New関数を使うと、次のような利点があります。
New関数は、初期化するstructと同じパッケージで宣言されることが多いため、そのstructのプライベートなフィールドも初期化できますこの型をさらに深く学びたい場合は、次のリソースを参照してください。Go by Example: Structs、A Tour of Go: Structs、Structures in Go (structs)
new組み込み関数structの新しいインスタンスを作成するもう1つの方法は、組み込みのnewを使うことです。
s := new(Shape) // s will be of type *Shape (pointer to shape)
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: size: 0
この例では、newはstructShapeのインスタンスを、すべての値をその型のゼロ値で初期化して作成し、そのポインターを返します。
structの新しいインスタンスがnewビルトインを使って作成されることは、ほとんどの場合ありません。
structリテラル、独自のNew関数、あるいはパッケージが提供する、structを組み立てるのに役立つその他の関数を常に優先して使いましょう。
newビルトインを使ってstructの新しいインスタンスを作成するのは、最後の手段にしましょう。