I have an interface Model
, which is implemented by struct Person
.
To get a model instance, I have the following helper functions:
func newModel(c string) Model { switch c { case "person": return newPerson() } return nil } func newPerson() *Person { return &Person{} }
The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).
When I attempted to do something similar for returning a slice of models, I get an error. Code:
func newModels(c string) []Model { switch c { case "person": return newPersons() } return nil } func newPersons() *[]Person { var models []Person return &models }
Go complains with: cannot use newPersons() (type []Person) as type []Model in return argument
My goal is to return a slice of whatever model type is requested (whether []Person
, []FutureModel
, []Terminator2000
, w/e). What am I missing, and how can I properly implement such a solution?
This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643
The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.
A []Person
and a []Model
have different memory layouts. This is because the types they are slices of have different memory layouts. A Model
is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person
is a struct whose size depends on the fields it contains. In order to convert from a []Person
to a []Model
, you will need to loop over the array and do a type conversion for each element.
Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.
models := make([]Model, len(persons)) for i, v := range persons { models[i] = Model(v) } return models
And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.
*[]Person // pointer to slice []*Person // slice of pointers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With