構造体へのインターフェースの埋め込みについての知識に漏れがあったので、調べたことをまとめました。
Goでは、インターフェースの明示的宣言はなく、インターフェースの持つメソッドを実装することでそのインターフェースを満たしていることになります(ダックタイピング)。
しかし、実はインターフェースを構造体に埋め込むことでも、例えその構造体はインターフェースの持つメソッドを持っていなくても、そのインターフェースを満たしていることになります。
下記のコードでは、user構造体はUserInterfaceを持っているのでUserInterfaceのもつFullName()を持っていなくてもUserInterfaceを満たしていることになります。よって、下記のコードはビルドが通ります。
func main() {
taro := testUser{
firstName: "Taro",
lastName: "Yamada",
}
outputUser(taro) //testUserがUserInterfaceを満たしているため、taroをoputputUserに渡せる
}
type UserInterface interface {
FullName() string
}
type testUser struct {
UserInterface // interfaceを埋め込むことで、メソッドを実装しなくてもそのinterfaceを満たせる
firstName, lastName string
}
func outputUser(u UserInterface) {
fmt.Println(u.FullName())//userはFullNameメソッドを持っていないがコンパイルエラーにならない
}
しかし、ouputUserメソッド内で実際には実装されていないFullName()メソッドを呼んでいるため、実行時にはpanicが起きます。
❯ go run main.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x10992c7]
goroutine 1 [running]:
main.main()
/Users/mmm/go/src/github.com/masalennon/test/main.go:13 +0x87
exit status 2
上記のコードに、FullNameメソッドを追加すれば、ちゃんと実行されます。
func (u user) FullName() string {
return u.firstName + " " + u.lastName
}
// Taro Yamada
おわり