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 results []dogs 。相反,我想以某种方式从我的 Stuff 结构中获取 []dogs 位,但我不知道如何。

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

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

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

关键是我想将这个 getAll 函数重用于任何其他类型,而不是为我的所有 63 只动物创建几乎相同的 getAll 函数。喵。

4

1 回答 1

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 解码器大量使用反射。

于 2014-09-10T17:33:24.090 回答