はじめに
構造体の初期化方法の違いについてまとめました。
実行環境
本記事で使用する構造体
以下の構造体を例に説明していきます。
//
// 親クラス(のようなもの)
//
type Animal struct {
Name string
Age int
}
//
// 子クラス(のようなもの)
//
type Cat struct {
Animal // 構造体の埋め込み(以下の「補足」を参照)
ServantName string
}
## 補足(構造体の埋め込みについて)
Go 言語に「クラスの継承」という概念はありません。しかし、「構造体の埋め込み」を使うことで、それに似たようなことが実現できます。
//
// Cat 構造体の初期化
//
c := Cat{}
//
// Name は本来 Animal 構造体のフィールド変数だが、「構造体の埋め込み」を使うことで、
// Cat 構造体のフィールド変数と同じようにアクセスすることができる。
//
c.Name = "kuro"
fmt.Println(c.Name) // => kuro
詳細は、実践Go言語を参照してください。
複数行で初期化する方法
Animal 構造体(親クラスのようなもの)
a := Animal{}
// var a Animal = Animal{} // 上記と同じ意味
// var a Animal // 上記と同じ意味
a.Name = "hoge"
a.Age = 5
Cat 構造体(子クラスのようなもの)
c := Cat{}
// var c Cat = Cat{} // 上記と同じ意味
// var c Cat // 上記と同じ意味
c.Name = "kuro"
c.Age = 1
c.ServantName = "taro"
一行で初期化する方法
Animal 構造体(親クラスのようなもの)
フィールド名を指定しない場合
a := Animal{"hoge", 5}
// var a Animal = Animal{"hoge", 5} // 上記と同じ意味
フィールド変数の一部を省略することはできません。
a := Animal{"hoge"} // => too few values in struct initializer
フィールド名を指定する場合
フィールド変数の順番は好きなように指定できます。
a1 := Animal{Name: "hoge", Age: 5}
a2 := Animal{Age: 5, Name: "hoge"}
フィールド名を指定する場合は、フィールド変数の一部を省略することができます。
a1 := Animal{Age: 5} // => { 5} : Name はゼロ値(string 型の場合は、空文字列)になる
a2 := Animal{Name: "hoge"} // => {hoge 0} : Age はゼロ値(int 型の場合は、0)になる
Cat 構造体(子クラスのようなもの)
フィールド名を指定しない場合
c := Cat{Animal{"kuro", 1}, "taro"}
// var c Cat = Cat{Animal{"kuro", 1}, "taro"} // 上記と同じ意味
フィールド変数の一部を省略することはできません。
c := Cat{Animal{"kuro", 1}} // => too few values in struct initializer
フィールド名を指定する場合
フィールド変数の順番は好きなように指定できます。
c1 := Cat{Animal: Animal{"kuro", 1}, ServantName: "taro"}
c2 := Cat{ServantName: "taro", Animal: Animal{"kuro", 1}}
フィールド名を指定する場合は、フィールド変数の一部を省略することができます。
c := Cat{Animal: Animal{"kuro", 1}} // => {{kuro 1} } : ServantName はゼロ値(string 型の場合は、空文字列)になる
c := Cat{ServantName: "taro"} // => {{ 0} taro} : Animal 構造体の各フィールド(Name:string型、Age:int型)はゼロ値になる
new を使う方法
a := new(Animal)
// a := &Animal{} // 上記と同じ意味
a.Name = "hoge"
a.Age = 5
new(Animal)
は、&Animal{}
と同じ意味です。new(Animal)
は、Animal 構造体へのポインタを返します。
new(Animal) と &Animal{} の違い
&Animal{}
は、一行で初期化することができますが、new(Animal)
はできません。
//
// 一行で初期化できる。
//
a1 := &Animal{"hoge", 5}
//
// 一行で初期化できない。new(Animal) でなければならない。
//
a2 := new(Animal{"hoge", 5}) // => Animal literal is not a type
おまけ(make について)
make はマップ、スライス、チャネルを初期化するために使う関数です。構造体の初期化には使えません。new と混同しやすいので注意してください。
a := make(Animal) // => cannot make type Animal
参考文献
How to Initializing embedded struct field using a struct literal?