問題
Go言語はinterface
による型の制約ができる。逆にinterface
で宣言したメソッドをすべて満たすいかなるstruct
もそのinterface
を満たすものとして扱える。いわゆるダックタイピング。
参考
で、interfaceを満たすstructを定義したつもりが「インターフェース実装できてないよ!そのメソッドはポインターを取らなきゃ!」と叱られる。
原文(これはうごかない)
package main type Greeter interface { Greet() } type Person struct { name string } func (p *Person) Greet() { println("Hi! I'm ", p.name) } func GetGreeterByName(name string) Greeter { return Person{name} } func main() { p := GetGreeterByName("otiai10") p.Greet() }
prog.go:13: cannot use Person literal (type Person) as type Greeter in return argument: Person does not implement Greeter (Greet method has pointer receiver) [process exited with non-zero status]
ふぇぇ
調査
このスレッドが一番わかりやすい
解決
package main type Greeter interface { Greet() ChangeNameTo(new string) } type Person struct { name string } func (p *Person) Greet() { println("Hi! I'm ", p.name) } func (p *Person) ChangeNameTo(new string) { p.name = new } func GetGreeterByName(name string) Greeter { // ここで参照を返す return &Person{name} } func main() { p := GetGreeterByName("otiai10") p.Greet() p.ChangeNameTo("otiai12") p.Greet() } // Hi! I'm otiai10 // Hi! I'm otiai12
つまり
interface
の定義は、その型がバリューだろうとポインタだろうと、どっちでも定義可能で、しかしながらメソッドのなかでポインタで扱うんだったらお前それポインタなんだよな?な?ということ。 (p Person)
を取るメソッドだけの定義だったら返すPerson
は&Person{}
ではなくPerson{}
でいい。
そんかし、そん時はもちろんポインタじゃないのでメソッド内で自身を上書きできない。↓
package main type Greeter interface { Greet() ChangeNameTo(new string) } type Person struct { name string } func (p Person) Greet() { println("Hi! I'm ", p.name) } func (p Person) ChangeNameTo(new string) { p.name = new } func GetGreeterByName(name string) Greeter { return Person{name} } func main() { p := GetGreeterByName("otiai10") p.Greet() p.ChangeNameTo("otiai12") p.Greet() } // Hi! I'm otiai10 // Hi! I'm otiai10
雑感
これが雑感です。
DRYな備忘録