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 で犬の型として宣言せずに、 Stuff 構造体に s := NewStuff(collection, dogs) のようなことを行うにはどうすればよいでしょうか (それは何でもかまいませんが、別の関数では、私が知っているすべての猫である可能性があります...) ?

ポイントは、63 匹の動物すべてに対してほぼ同じ getAll 関数を作成するのではなく、この 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 に答える