Reputation: 6184
I have a Go package that has a large number of (auto-generated) models:
Tax2001_1
Tax2001_2
Tax2001_3
...
Tax2020_1
Each is defined like this:
func NewTax2011_1() *Tax2011_1 {
return &Tax2011_1 { ... }
}
I want to access them depending on a value (timestamp) that is only known at runtime. So I am trying to put the model constructors into a map:
package tax
type TaxModel interface {
Calculate()
}
var taxModels = make(map[string]func() *TaxModel)
func init() {
...
taxModels["2011_1"] = NewTax2011_1
taxModels["2011_2"] = NewTax2011_2
...
}
The above code is not correct:
cannot use NewTax2011_1 (type func() *Tax2011_1) as type func() *TaxModel in assignment
Any hint how to achieve that?
Upvotes: 1
Views: 50
Reputation: 54355
Here's a test I made which seems to work. Looks like you need to not use a pointer to interface. That is what seems to be the problem.
package main
import "fmt"
type Model_1 struct {
Name string
}
type Model_2 struct {
Name string
}
func (m *Model_1) Calculate() int64 {
return 0
}
func (m *Model_2) Calculate() int64 {
return 0
}
type Model interface {
Calculate() int64
}
func main() {
m := make(map[string]func() Model)
m["test"] = func() Model {
return &Model_1{Name: "m"}
}
fmt.Println(m["test"]().Calculate())
}
Upvotes: 1
Reputation: 51622
Assuming Tax2011_1
and its friends implement TaxModel
interface, you can declare the constructor to return the interface:
func NewTax2011_1() TaxModel {
return &Tax2011_1{}
}
You should not use an interface pointer:
var taxModels = make(map[string]func() TaxModel)
Then it should work.
If you cannot change the constructors, you can use an adapter function:
func NewTax2011_1() *Tax2011_1 {...}
var taxModels = make(map[string]func() TaxModel)
func init() {
...
taxModels["2011_1"] = func() TaxModel {return NewTax2011_1()}
taxModels["2011_2"] = func () TaxModel {return NewTax2011_2() }
...
}
Upvotes: 3