Golang で struct を embed する際の注意点


TL;DR

embed する際に型を指定した場合としていない場合で、フィールドへの参照の仕方が異なる。

struct を embed する

Go には継承という概念はないが、その代替手段として embed(埋め込み)という手段がよく使われる。struct の場合、 embed は下記のようになる。

type Person struct {
    Name string
    Age  int
}

type Account struct {
    Person
    Field1 string
    Field2 string
}

この場合、AccountPerson.Name フィールドへのアクセスは、Account.Name のような形でできる。(Account.Person.Name としなくてよい

型を指定して struct を embed する

しかし、型を指定して下記のように定義した場合は、Account.Person.Name としなくてはならない。

type Person struct {
    Name string
    Age  int
}

type Account struct {
    Person Person // 型指定
    Field1 string
    Field2 string
}

サンプルコード

main.go
package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 型指定なし
type Foo struct {
    Person
    Field1 string
    Field2 string
}

// 型指定あり
type Bar struct {
    Person Person
    Field1 string
    Field2 string
}

func main() {
    foo := Foo{
        Person{"型指定なし", 10},
        "a",
        "b",
    }

    bar := Bar{
        Person{"型指定あり", 20},
        "a",
        "b",
    }

    fmt.Println(foo)      // {{型指定なし 10} a b}
    fmt.Println(bar)      // {{型指定あり 20} a b}
    fmt.Println(foo.Name) // 型指定なし
    fmt.Println(bar.Name) // bar.Name undefined (type Bar has no field or method X)
}