考虑以下工厂:Go playground
type TypeA struct {
placeholder int
}
func NewTypeA() *TypeA {
return new(TypeA)
}
func main() {
factory := make(map[string]func() interface{})
factory["TypeA"] = NewTypeA
}
这给了我以下错误:cannot use NewTypeA (type func() *TypeA) as type func() interface {} in assignment
非常清楚。
我认为interface{}
能够与指针匹配。
我找到了这个解决方案:Go playground
type Entity interface {}
type TypeA struct {
Entity
placeholder int
}
func NewTypeA() Entity {
return new(TypeA)
}
func main() {
var tmp interface{}
factory := make(map[string]func() Entity)
factory["TypeA"] = NewTypeA
tmp = factory["TypeA"]()
log.Println(reflect.TypeOf(tmp))
}
这给了我预期的类型*TypeA
。
有没有其他方法可以直接使用interface{}
类型而不是“哑”界面(Entity
)来执行此操作?
答案 0 :(得分:3)
我不认为你完全理解接口{}是什么,因此试图错误地使用它。
如this article中所述:
接口{}类型,空接口,是很多的来源 混乱。
我建议你阅读那篇文章,然后再看看你想要做什么。
接口{}不是任何其他类型的占位符,而是type itself。
因此,如果您创建一个将返回接口{}的函数作为键的映射,那么这就是函数需要返回的类型。不是指针或int或其他任何东西。
虽然您可以为接口指定任何类型的值,包括指针类型,但您不能使用其他类型代替接口{}类型。
您要完成的工作似乎是拥有一个可以返回任何类型值的函数的映射。您只能通过不同的方式设计功能来间接地做到这一点。您必须在函数中使用interface {}类型,指定要返回的值,然后返回接口{}。但是你必须返回类型接口{}而不是类型int或string或* TypeA或其他。
答案 1 :(得分:1)
在您的第二个示例中NewTypeA()
返回Entity
而不是*TypeA
,因此它与NewTypeA()
将返回interface{}
的解决方案没有区别{1}}类型完全不必要/冗余:
Entity
输出(在Go Playground上尝试):
type TypeA struct {
placeholder int
}
func NewTypeA() interface{} {
return new(TypeA)
}
func main() {
factory := make(map[string]func() interface{})
factory["TypeA"] = NewTypeA
tmp := factory["TypeA"]()
fmt.Printf("%T", tmp)
}
*main.TypeA
返回类型为方便起见,如果您希望*TypeA
工厂函数仍然返回NewTypeA()
,可以在*TypeA
地图中添加匿名包装函数来实现:
factory
再次输出(Go Playground):
func NewTypeA() *TypeA {
return new(TypeA)
}
func main() {
factory := make(map[string]func() interface{})
factory["TypeA"] = func() interface{} { return NewTypeA() }
tmp := factory["TypeA"]()
fmt.Printf("%T", tmp)
}