2014-09-10 3 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. Вместо этого я хотел бы получить, что [] собаки немного из моей структуры Stuff каким-то образом, но я не могу понять, как это сделать.

это, как я называю эту функцию:

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

Так как я мог бы сделать что-то вроде с: = NewStuff (сбор, собаки) к моему Материала структуры без объявления как тип собаки в веществе (его может быть что угодно, в другой функции это могут быть кошки для всего, что я знаю ...)?

Дело в том, что я хочу повторно использовать эту функцию getAll для любых других типов, вместо того чтобы делать почти идентичную функцию getAll для всех моих 63 животных. Мяу.

ответ

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().() Отправляет запрос серверу базы данных и ожидает ответа. Ответ с сервера распаковывается с использованием декодера BSON Mgo. Декодер BSON сильно использует отражение.

 Смежные вопросы

  • Нет связанных вопросов^_^