Reputation: 4596
I'm trying to implement a factory function that will return an instance of one of many structs that fulfil the contract of an interface X
.
m := make(map[string] ?)
func init () {
m["a"] = ?
m["b"] = ?
}
type X interface {
y()
}
type A struct {}
func (a * A) y () {}
type B struct {}
func (b * B) y () {}
function factory(name string) X {
return &m[name]{}
}
The code above is just a simplified demonstration of what I'm trying to achieve - looking for pointers for whether this is possible, or if there is a different go idiom to solve this kind of requirement that I'm missing.
Upvotes: 1
Views: 96
Reputation: 7878
If you have a simple value type then as @VonC said, you can just use map[string]X
and return a copy of the exemplar value.
For anything else, instead of using reflection, I'd just use a map of creation functions. Like what the image
package does with
image.RegisterFormat
.
E.g. (playground):
package main
import "fmt"
type X interface {
y()
}
type newXFunc func() X
// Here just a map variable and two functions, but
// this could be a type with two methods instead.
var m = map[string]newXFunc{}
func register(name string, fn newXFunc) {
m[name] = fn
}
func factory(name string) X {
return m[name]()
}
func init() {
// If register is exported than these
// calls can be in other packages that
// implement A and B.
register("a", NewA)
// For simple things that don't have/need
// their own stand-alone "new" function.
register("b", func() X { return B{} })
}
type A struct{}
func (a *A) y() {}
func NewA() X { return &A{} }
type B struct{}
func (b B) y() {}
func main() {
a1 := factory("a")
b1 := factory("b")
fmt.Printf("%T\n", a1)
fmt.Printf("%T\n", b1)
}
Upvotes: 1
Reputation: 1324537
You can use map[string]X
, with X the interface (which can reference a value or a pointer of any object respecting X contract)
or if there is a different go idiom to solve this kind of requirement that I'm missing?
You can also use reflection (as in "Instance new Type") to implement your factory.
reflect.New(yourtype).Elem().Interface()
You can see a factory example in "is there a way to create an instance of a struct from a string?".
The quicker approach for a factory method (returning a new instance each time) is using a switch (like in this example):
// Create a new Widget interface based on WidgetType and set WidgetInfo
func New(wt WidgetType, wi WidgetInfo) Widget_iface {
switch wt {
case Widget_A:
return newWidgetA(wi)
case Widget_B:
return newWidgetB(wi)
}
return nil
}
Upvotes: 1