转到另一个结构中的自定义结构类型

时间:2014-09-10 14:59:56

标签: struct go mgo

我很难理解如何在另一个结构中保存自定义结构(在很多其他结构中)。目前我的代码如下所示:

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 results [] dog。相反,我想以某种方式从我的Stuff结构中得到那些[]狗,但我无法弄清楚如何。

这就是我调用此函数的方式:

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

那么我怎么能做s:= NewStuff(集合,狗)之类的东西到我的Stuff结构而不将其声明为Stuff中的狗类型(它可能是任何东西,在另一个函数中它可能是我所知道的所有猫。 ..)?

重点是我想将这个getAll函数重用于其他任何类型,而不是为我的63只动物制作几乎相同的getAll函数。喵。

1 个答案:

答案 0 :(得分: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
}

构建Dog集合:

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

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