Interfaceポインタの型エラー - golang

2020-04-13

Iocコンテナを作ろうとして次のようなコードを書くとエラーが出ました。
原因はinterfaceのポインタの型エラー。

// interface
type IFace interface {
    hello() string
}

// concrete type
type Concrete struct {
}

func NewConcrete() *Concrete {
    return &Concrete{}
}

// - implementation
func (c *Concrete) hello() string {
    return "Hi"
}

// ioc
type Ioc struct {
}

func NewIoc() *Ioc {
    return &Ioc{}
}

// NG: this method raises error
// これは次のようなエラーがでる
// cannot use NewConcrete() (type *Concrete) as type *IFace in return argument:
// *IFace is pointer to interface, not interface
func (i *Ioc) IFace() *IFace {
	return NewConcrete()
}

// こちらはOK
func (i *Ioc) IFace() IFace {
	return NewConcrete()
}

func main() {
    i := NewIoc()
    ic := i.IFace()
    // ...
}

いくつ書き換えるとOK。
しかし綺麗ではない。

// value receiverにする
func (c Concrete) hello() string {
    return "Hi"
}

...

// 型を明示的に指定していれるとOK
func (i *Ioc) IFace() *IFace {
    var vif IFace
    var pif *IFace
    vif = *NewConcrete()
    pif = &vif
    return pif
}

structと同様に、ポインタを返したほうがコピーされる時のコストが低くなるかと思いきや、そもそもinterfaceはポインタ2個分なのでそれほどコストがかからない。 https://groups.google.com/forum/#!topic/golang-nuts/N9f70MZUulk

ちゃんとA Tour Of Goにも書いてますね……
https://tour.golang.org/methods/11

参考

https://groups.google.com/forum/#!topic/golang-nuts/N9f70MZUulk
https://play.golang.org/p/5YquxHKRWL