如何让golang接口实现返回另一个接口的实现?

时间:2017-11-12 07:54:57

标签: go

具体示例如下:https://play.golang.org/p/ZNmviKWLwe

我有一个接口A.我希望A的所有实现都有一定的签名(因此接口)。我希望其中一个返回实现另一个接口的有用的东西。

type Box interface {
    GetToy(int) (*Toy, error)
}
type Toy interface{
    Play()
}


type CarBox struct {
   Length int
   Width int
   Height int
   toys []*Matchbox
}
type Matchbox struct {}

func (b *CarBox) Size () int {
    return b.Length*b.Width*b.Height
}
func (b *CarBox) GetToy(j int) (*Matchbox, error) {
    return b.toys[j], nil
}
func (m *Matchbox) Play() {
    fmt.Println("Zoom!")
}

但当然,它不起作用,因为GetToy()返回*Matchbox而不是*Toy,即使MatchboxToy完全可以接受的实现1}}。而且,不,它不是因为指针;无论我在*Toy中返回GetToy还是仅在Toy返回{<1}},都会得到相同的结果:

tmp/sandbox721971102/main.go:33:15: cannot use CarBox literal (type CarBox) as type Box in return argument:
    CarBox does not implement Box (wrong type for GetToy method)
        have GetToy(int) (*Matchbox, error)
        want GetToy(int) (*Toy, error)

显然,我的模式并不匹配如何运作。什么是&#34;正确&#34;这样做的方法?

2 个答案:

答案 0 :(得分:4)

首先,您几乎不需要指向接口类型的指针。因此,GetToy方法签名应更改为:

type Box interface {
    GetToy(int) (Toy, error) // use Toy, not *Toy
}

现在,请注意隐式地按类型满足接口。因此,通过实现Play()方法,*Matchbox隐式满足Toy接口(请注意*,实现Toy接口的类型为指向Matchbox 而非Matchbox 的指针。

这意味着类型*Matchbox的值可以替换为类型Toy。那么剩下的就是修复GetToy上定义的*CarBox方法:

func (b *CarBox) GetToy(j int) (Toy, error) {
    return b.toys[j], nil
}

现在上面GetToy将返回*Matchbox,它确实实现了Toy界面。

答案 1 :(得分:1)

一些修正:https://play.golang.org/p/-mDr5SDZvV

指向界面的指针是非常需要的东西。使用界面 - 它可以包含具体类型。

<强>更新: 如果你希望有一个像func (b *CarBox) GetToy(j int)这样的指针接收器的方法,你可以从Tester函数返回指针(注意&amp; ):

func Tester() Box {
    return &CarBox{}
}

这样,从Tester返回的接口值将结束指向CarBox实例的指针。因此Go运行时将能够使用指针接收器运行方法。否则只有一个值而不是一个指针。因此,只能调用带有值接收器的方法。