最近GO言語を勉強していて、ネスト(入れ子)された構造体のフィールドにアクセスする際のことをメモしておきます。
以下のように、中にmydata1をもつ構造体maindataを作ってみます。
package main
import "fmt"
type mydata1 struct {
a int
b int
c int
}
type maindata struct {
m1 mydata1
e int
}
func main() {
d1 := mydata1{a: 11, b: 12, c: 13}
mdata := maindata{m1: d1, e: 99}
fmt.Println(mdata)
fmt.Println(mdata.m1.a)
fmt.Println(mdata.m1.b)
fmt.Println(mdata.m1.c)
fmt.Println(mdata.e)
}
上記のように、mydata1は、m1というフィールド名で定義されているので、mydata1のa~cにアクセスするには、mdata.m1.X と書く必要があります。上記を実行すると以下のようになります。想定通りですよね。
{{11 12 13} 99} 11 12 13 99
maindata構造体を定義するときに、フィールド名を省略することができるようです。省略すると、以下のようにmaindataのフィールド名を省略し直接mydata1のフィールド名にアクセスできるようです。なお、構造体を初期化する時、フィールド名が無いので型名(mydata1)を使うようです。
package main
import "fmt"
type mydata1 struct {
a int
b int
c int
}
type maindata struct {
mydata1
e int
}
func main() {
d1 := mydata1{a: 11, b: 12, c: 13}
mdata := maindata{mydata1: d1, e: 99}
fmt.Println(mdata)
fmt.Println(mdata.a)
fmt.Println(mdata.b)
fmt.Println(mdata.c)
fmt.Println(mdata.e)
}
これを実行すると以下のようになります。
{{11 12 13} 99} 11 12 13 99
では、以下のように、maindataに、mydata1と同じフィールド名があるとどうなるのでしょうか?
package main
import "fmt"
type mydata1 struct {
a int
b int
c int
}
type maindata struct {
mydata1
a int
}
func main() {
d1 := mydata1{a: 11, b: 12, c: 13}
mdata := maindata{mydata1: d1, a: 99}
fmt.Println(mdata)
fmt.Println(mdata.a)
}
これを実行すると、以下のように、親(ネスト元)のフィールドaの値が優先されるようです。
{{11 12 13} 99} 99
では、ネストする構造体が2つ以上あり、その構造体に同じフィールド名があるとどうなるのでしょうか?やってみます。
import "fmt"
type mydata1 struct {
a int
b int
c int
}
type mydata2 struct {
a int
b int
c int
}
type maindata struct {
mydata1
mydata2
a int
}
func main() {
d1 := mydata1{a: 11, b: 12, c: 13}
d2 := mydata2{a: 21, b: 22, c: 23}
mdata := maindata{mydata1: d1, mydata2: d2, a: 99}
fmt.Println(mdata)
fmt.Println(mdata.b)
}
これを実行すると、以下のようにmydata1にもmydata2にもbというフィールドがあって曖昧なため、コンパイル時にエラーになりました。
./main.go:28:19: ambiguous selector mdata.b
なお、上記はmdata.bにアクセスしていますが、mdata.aの場合、親にaというフィールドがあるため、コンパイルエラーにならず、99が表示されます。
以上、GO言語の実験でした。
環境 : GOバージョン 1.11.4 on Linux