2014-09-10 83 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解碼器大量使用反射。