結論
簡潔に言うと「interface を指すポインタは interface を実装した構造体のポインタのポインタになるから」です。
これだけではよくわからないので詳しくみていきましょう。
interface のポインタからメソッドコールができないとは?
interface の Mammal とそれを実装した Human という構造体を考えましょう。
type Mammal interface {
GetAge() int
}
type Human struct {
Age int
}
func (h *Human) GetAge() int {
return h.Age
}
この時、以下のように Mammal というインターフェースのポインタから GetAge() をコールしようとするとコンパイルエラーになってしまいます。
func Foo(human *Mammal) {
_ = human.GetAge() // コンパイルエラー
}
GetAge() をコールするためには *Mammal ではなく Mammal を引数に取る必要があります。
func Foo(human Mammal) {
_ = human.GetAge()
}
そもそも Go 言語の interface とは?
以下のブログにわかりやすく Go の interface とは何かが説明されています。ざっくりまとめると、 interface は型情報と値情報をフィールドに持った構造体になります。これらの型情報と値情報は interface を受ける変数に代入されることで、動的に変化するようです。
interface のポインタ
変数 human が interface の Mammal そのものを指す場合、以下の図のようになり、構造体の実体からはポインタに当たるものなので GetAge() をコールすることができます。
しかし、human が interface の Mammal のポインタの場合、下の図を見ると、構造体の実体からはポインタのポインタに当たるものになってしまっているので GetAge() をコールすることができなかった訳です。
ポインタのポインタは 1 段階デリファレンスしてやれば最終的な参照先のメソッドをコールすることができます。つまり、interface のポインタはデリファレンスしてやることでメソッドコールが可能になると言うことです。
func Foo(human *Mammal) {
_ = (*human).GetAge()
}