Go:工厂返回指针和接口{}类型

时间:2015-05-27 08:19:20

标签: interface go factory

考虑以下工厂: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)来执行此操作?

2 个答案:

答案 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)
}