Golang函数返回一个接口

时间:2016-01-26 03:32:25

标签: go

下面的代码实际上是不言自明的。

为什么我可以说CreateLion()的结果,一个实现Cat接口的结构的指针,是Cat接口的一个实例,但我不能说CreateLion()的类型为“返回Cat界面。“

实现此类行为的标准Golang方法是什么?

package main

import "fmt"

func main() {
    var lion Cat := CreateLion()
    lion.Meow()

    // this line breaks. Why?
    var cf CatFactory = CreateLion
}

type Cat interface {
    Meow()
}

type Lion struct {}
func (l Lion) Meow() {
    fmt.Println("Roar")
}

// define a functor that returns a Cat interface
type CatFactory func() Cat

// define a function that returns a pointer to a Lion struct
func CreateLion() *Lion {
    return &Lion{}
}

4 个答案:

答案 0 :(得分:7)

试试这个:

package main

import "fmt"

type Cat interface {
    Meow()
}

type Lion struct{}

func (l Lion) Meow() {
    fmt.Println("Roar")
}

type CatFactory func() Cat

func CreateLion() Cat {
    return Lion{}
}

func main() {
    lion := CreateLion()
    lion.Meow()

    var cf CatFactory = CreateLion
    fLion := cf()
    fLion.Meow()
}

在大多数情况下,您可以将任何类型分配给基本类型interface{}。但是,如果函数参数的类型是map[T]interface{}[]interface{}func() interface{},情况会发生变化。 在这种情况下,类型必须相同。

答案 1 :(得分:3)

我认为你应该阅读这篇博文http://blog.golang.org/laws-of-reflection,它确切地说明了变量,类型和接口之间的关系。

在您的示例中,*LionCat不同。

您可以更正从CreateLion*Lion的功能Cat

答案 2 :(得分:2)

这里的问题是静态类型去区分“这是一个返回猫的函数”,“这是一个返回狮子的函数”,因此不会接受另一个。

解决此问题的方法是为您的工厂提供完全符合预期的工厂:

var cf CatFactory = func() Cat{
    return CreateLion()
}
catlion := cf()
catlion.Meow()

答案 3 :(得分:0)

进行一些更改即可正常工作。在此处查看:https://play.golang.org/p/ECSpoOIuzEx

package main

import "fmt"

func main() {
    lion := CreateLion() // Go idomatic style recommends 
                         // allowing the compiler to divine the type
    lion.Meow()

    CatFactory := CreateLion
    _ = CatFactory // Go doesn't like unused variables and fails the build

    obj := CatFactory()     // exercising our factory method
    obj.Meow()
}

type Cat interface {
    Meow()
}

type Lion struct {}
func (l Lion) Meow() {
    fmt.Println("Roar")
}

// define a functor that returns a Cat interface
type CatFactory func() Cat

// define a function that returns a pointer to a Lion struct
func CreateLion() *Lion {
    return &Lion{}
}

此外,尽管Go没有Java样式的接口,但它确实具有接口并且可以实现多态,但是类型在编译时就已知。

如果两种类型都实现相同的接口,则可以为“是”关系建模。但是,在将对象传递到接受该接口类型的函数之前,它不会强制执行该接口。因此,如果您想实现策略模式,则在传递策略对象匹配接口“ Cat”时,该函数将接受“ Lion”对象,或任何其他使用正确签名实现Meow函数的类。

此外,工厂方法在Go中绝对必要且有用。实际上,在Go中,您可以使用工厂函数来构造对象,而不是使用构造函数。