Edited at

[Go] 構造体の初期化方法まとめ

More than 3 years have passed since last update.


はじめに

構造体の初期化方法の違いについてまとめました。


実行環境

Go Playground (go1.3.1)


本記事で使用する構造体

以下の構造体を例に説明していきます。

//

// 親クラス(のようなもの)
//
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


参考文献

実践Go言語

How to Initializing embedded struct field using a struct literal?