转到:工厂返回的指针和接口{}类型

Consider the following 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
}

This gives me the following error: cannot use NewTypeA (type func() *TypeA) as type func() interface {} in assignment which is pretty clear.

I thought that interface{} was able to be matched with a pointer.

I found this solution: 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))
}

Which gives me the expected type *TypeA. Is there an other way to do this using the interface{} type directly instead of a "dumb" interface (Entity)?

In your 2nd example NewTypeA() returns Entity not *TypeA, so it is no different from a solution where NewTypeA() would return interface{} which renders the Entity type completely needless/redundant:

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

Output (try it on the Go Playground):

*main.TypeA

Keeping the *TypeA return type

For convenience if you want your NewTypeA() factory function to still return *TypeA, you can do so by putting an anonymous wrapper function in your factory map:

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

Output again (Go Playground):

*main.TypeA

I don't think you fully understand what an interface{} is and thus are trying to use it incorrectly.

As stated in this article:

The interface{} type, the empty interface, is the source of much confusion.

I'd recommend that you read that article and then have another look at what you are trying to do.

An interface{} is not a placeholder for any other type, it's a type itself.

So if you create a map that takes functions that return interface{} as keys then that's the type the functions needs to return. Not a pointer or int or anything else.

While you can assign a value of any type to an interface, including pointer types, you can't use other types in place of an interface{} type.

It seems that what you are trying to accomplish is have a map with functions that can return a value of any type. You can only do that indirectly by designing your functions differently. You'd have to use an interface{} type in the function, assign the value you want to return to it and then return the interface{}. But you have to return type interface{} and not type int or string or *TypeA or whatever.