Reputation: 647
I'm struggling to understand how to save a custom struct in another struct (amongst great many other things). Currently my code looks like this:
type dogs struct {
bleeh string
blaah string
bluuh string
}
type Stuff struct {
collection *mgo.Collection
//myAnimalStruct what type comes here?
}
func NewStuff(c *mgo.Collection) *Stuff {
return &Stuff{
collection: c
}
}
func getAll(s *Stuff) interface{} {
collection = s.collection
var results []dogs
err := collection.Find(bson.M{}).All(&results)
if err != nil {
panic(err)
}
return results
}
Now, I would like to get rid of that var results []dogs in getAll function. Instead, I would like to get that []dogs bit from my Stuff struct somehow, but I can't figure out how.
this is how I call this function:
func getMeDogs(w http.ResponseWriter, r *http.Request) interface{} {
collection = Collection("animals")
s := NewStuff(collection)
return getAll(s)
}
So how could I do something like s := NewStuff(collection, dogs) to my Stuff struct without declaring it as a dog type in Stuff (it could be anything, in another function it could be cats for all I know...)?
The point is that I want to reuse this getAll function for whatever other types, instead of making nearly identical getAll function for all of my 63 animals. Meow.
Upvotes: 1
Views: 1957
Reputation: 6425
You can store a prototypical value of the type in Stuff and use reflection to create a pointer to a value of that type.
type Stuff struct {
collection *mgo.Collection
v interface{} // the prototype value
}
func NewStuff(c *mgo.Collection, v interface{}) *Stuff {
return &Stuff{
collection: c,
v: v,
}
}
func getAll(s *Stuff) (interface{}, error) {
p := reflect.New(reflect.TypeOf(s.v))
if err := s.collection.Find(bson.M{}).All(p.Interface()); err != nil {
return nil, err
}
return p.Elem().Interface(), nil
}
To construct a Dog collection:
s := NewStuff(collection, []Dog{})
Some people will say that reflection is slow. That's true, but in this case the cost is small compared to the cost of executing Find().All(). The call to Find().All() sends a request to the database server and waits for the response. The response from the server is unpacked using Mgo's BSON decoder. The BSON decoder makes heavy use of reflection.
Upvotes: 3