2014-09-10 97 views
1

我很努力去了解如何将自定义结构保存在另一个结构中(以及许多其他事物)。目前我的代码是这样的:去和另一个结构中的自定义结构类型

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 
} 

现在,我想摆脱getAll函数中的var结果[]狗。相反,我想以某种方式从我的Stuff结构中获得[]狗,但我无法弄清楚。

这是我如何调用该函数:

func getMeDogs(w http.ResponseWriter, r *http.Request) interface{} { 
    collection = Collection("animals") 
    s := NewStuff(collection) 
    return getAll(s) 
} 

所以,我怎么可以做类似S:= Newstuff文件(收集,狗)到我的东西结构没有宣布它作为东西狗型(其可以是任何东西,在另一个功能,它可能是我知道的所有猫...)?

问题是我想重复使用这个getAll函数用于其他类型的任何其他类型,而不是为我的63个动物创建几乎完全相同的getAll函数。喵。

回答

3

您可以在Stuff中存储该类型的原型值,并使用反射来创建指向该类型值的指针。

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 
} 

构建一个狗集合:

s := NewStuff(collection, []Dog{}) 

有人会说,反思是缓慢的。这是真的,但在这种情况下,与执行Find()。All()的代价相比,代价很小。对Find()。All()的调用向数据库服务器发送请求并等待响应。使用Mgo的BSON解码器解开服务器的响应。 BSON解码器大量使用反射。