Go

[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?