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
*TypeA
return typeFor 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.