为什么我可以说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{}
}
5条答案
按热度按时间3z6pesqy1#
试试这个:
在大多数情况下,可以将任何类型赋给基类型
interface{}
。但如果函数参数的类型是map[T]interface{}
,[]interface{}
或func() interface{}
,情况就不同了。在这种情况下,类型必须相同。zf2sa74q2#
我想你应该读一下这个博客http://blog.golang.org/laws-of-reflection,它是关于变量,类型和接口之间关系的精确描述。
在您的示例中,
*Lion
与Cat
不同。您可以将函数
CreateLion
的返回值从*Lion
更正为Cat
。8oomwypt3#
这里的问题是,静态类型的go将“this is a function that returns a cat”与“this is a function that returns a lion that is a cat”区分开来,因此不会接受一个作为另一个。
解决这个问题的方法是给予你的工厂var它所期望的:
jmo0nnb34#
Go不需要任何特殊的逻辑来处理你请求的任务,它会隐式地将 *Lion转换为接口Cat
示例:
试试这里:https://go.dev/play/p/PFp3fnXP8YH
djmepvbi5#
工作正常,有一些变化。在这里查看:https://play.golang.org/p/ECSpoOIuzEx
此外,尽管Go没有Java风格的接口,但它确实有接口,并且可以实现多态性,但类型在编译时是已知的。
如果两个类型实现相同的接口,则可以对“Is A”关系建模。但是,它不会强制接口,直到您将对象传递到接受该接口类型的函数中。因此,如果你想象实现策略模式,当你传入匹配接口“Cat”的策略对象时,该函数将接受一个“Lion”对象,或者任何其他实现了具有正确签名的Meow函数的类。
此外,工厂方法在Go中绝对是必要和有用的。事实上,在Go中,你使用工厂函数来构造对象,而不是构造函数。