##構造体の定義
さまざまな型をデータ構造のひとつの型として扱うことができます。Goはオブジェクト指向とは違う、メソッドの機能によって型を便利に扱えるような仕組みに設計されています。
一般的に構造体は予約語typeで型名を与え、任意のフィールドを定義します。
type 型名 struct { フィールド定義 }
##エイリアスの定義
先であげた予約語typeは、すでに定義されている型をもとに新しい型を定義するための機能です。そのため、下記のようにエイリアスを定義することができます。
type (
Ints [2]int
Strings []string
)
func main() {
i := Ints{5, 10}
s := Strings{"test1", "test2"}
fmt.Println(i) //[5 10]
fmt.Println(s) //[test1 test2]
}
エイリアスの定義では、同じ型の二つのエイリアスには互換性がないので注意が必要です。
##フィールド定義と複合リテラル
フィールドは下記のように定義します。
type Test struct {
A int
B int
}
func main() {
t := Test{A: 5, B: 10}
fmt.Println(t.A) //5
fmt.Println(t.B) //10
}
構造体型Testでint型のフィールドA, Bに初期値を指定して定義してます。このようにGoには、初期値を指定し構造体を生成する複合リテラルが用意されています。
ちなみに、フィールド定義ではメタ情報を付与するタグという機能があります。
type Test struct {
A int "test1"
B int "test2"
}
プログラムの実行には影響しませんが、jsonパッケージを使用するプログラムのなどで有効に活用されます。
##構造体の埋め込み
構造体に構造体型を定義するパターンがあります。
type Test1 struct {
A int
B int
}
type Test2 struct {
A int
Test1 Test1
}
func main() {
t := Test2{
A: 5,
Test1: Test1{
A: 6,
B: 12,
},
}
fmt.Println(t.Test1.A) //6
fmt.Println(t.Test1.B) //12
}
このように埋め込まれた構造体を変数に指定することで、埋め込んだ構造体型のフィールドに干渉することができます。
上記のプログラムでは、埋め込む構造体型を明示的にフィールド名を与えていましたが、フィールド名を省略しても同じ結果が得られます。しかし、暗黙的なフィールドの場合プリフィックスが無視されてしまうことに注意が必要です。
##組み込み関数new
組み込み関数newは、任意の型のポインタ型を生成するときに使用します。
type Test struct {
A int
B string
}
func main() {
a := new(Test)
fmt.Println(a.A) //0
fmt.Println(a.B) //
}
##メソッド
メソッドは下記のように定義します。
type Test struct {
A int
B string
}
func (a *Test) Example() {
fmt.Printf("%d, %s\n", a.A, a.B) //5, example
}
func main() {
b := &Test{A: 5, B: "example"}
b.Example()
}
このプログラムはa *Testはレシーバーを表しており、*Test型のメソッドExampleを定義し、変数bにアドレス演算子を使用した複合リテラルで初期化した値を呼び出して、出力しています。
これは、構造体型のポインタを使ったメソッドの定義でしたが、他の型や、エイリアスに対しても定義できる機能を持っています。
###型のコンストラクタ
Goでは、オブジェクト指向プログラミング言語でのコンストラクタ機能に代わって、New型名と定義することで型のコンストラクタを表すことができます。
##参考文献
著者 松尾愛賀
翔泳社 スターティングGo言語