Help us understand the problem. What is going on with this article?

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

More than 5 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?

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away