Go语言 函数返回接口

q35jwt9p  于 2023-06-27  发布在  Go
关注(0)|答案(5)|浏览(150)

为什么我可以说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{}
}
3z6pesqy

3z6pesqy1#

试试这个:

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{},情况就不同了。在这种情况下,类型必须相同。

zf2sa74q

zf2sa74q2#

我想你应该读一下这个博客http://blog.golang.org/laws-of-reflection,它是关于变量,类型和接口之间关系的精确描述。
在您的示例中,*LionCat不同。
您可以将函数CreateLion的返回值从*Lion更正为Cat

8oomwypt

8oomwypt3#

这里的问题是,静态类型的go将“this is a function that returns a cat”与“this is a function that returns a lion that is a cat”区分开来,因此不会接受一个作为另一个。
解决这个问题的方法是给予你的工厂var它所期望的:

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

jmo0nnb34#

Go不需要任何特殊的逻辑来处理你请求的任务,它会隐式地将 *Lion转换为接口Cat
示例:

package main

import "fmt"

type Cat interface {
    Meow()
}

type Lion struct{}

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

func CreateLion() *Lion {
    return &Lion{}
}

func main() {
    var lion *Lion = CreateLion()
    lion.Meow()

    var cf Cat = CreateLion()
    cf.Meow()
}

试试这里:https://go.dev/play/p/PFp3fnXP8YH

djmepvbi

djmepvbi5#

工作正常,有一些变化。在这里查看: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风格的接口,但它确实有接口,并且可以实现多态性,但类型在编译时是已知的。
如果两个类型实现相同的接口,则可以对“Is A”关系建模。但是,它不会强制接口,直到您将对象传递到接受该接口类型的函数中。因此,如果你想象实现策略模式,当你传入匹配接口“Cat”的策略对象时,该函数将接受一个“Lion”对象,或者任何其他实现了具有正确签名的Meow函数的类。
此外,工厂方法在Go中绝对是必要和有用的。事实上,在Go中,你使用工厂函数来构造对象,而不是构造函数。

相关问题