Абстрактная функция Golang, которая получает данные из массива db и заполняет
Я хочу создать абстрактную функцию, которая получает данные из БД и заполняет массив этими данными. Типы массивов могут быть разными. И я хочу сделать это без размышлений, из-за проблем с производительностью. Я просто хочу везде вызывать некоторые функции, такие как GetDBItems(), и получать массив данных из БД с нужным типом. Но все реализации, которые я создаю, являются обязательными.
Вот эта реализация функции:
type AbstractArrayGetter func(size int) []interface{}
func GetItems(arrayGetter AbstractArrayGetter) {
res := DBResponse{}
DB.Get(&res)
arr := arrayGetter(len(res.Rows))
for i := 0; i < len(res.Rows); i++ {
json.Unmarshal(res.Rows[i].Value, &obj[i])
}
}
Здесь я называю эту функцию:
var events []Event
GetFullItems("events", "events_list", map[string]interface{}{}, func(size int) []interface{} {
events = make([]Event, size, size)
proxyEnt := make([]interface{}, size, size)
for i, _ := range events {
proxyEnt[i] = &events[i]
}
return proxyEnt
})
Это работает, но есть много кода для вызова этой функции, также есть некоторая проблема производительности при копировании массива событий в массив интерфейсов.
Как я могу сделать это без отражения и сделать это с помощью короткого кода вызова функции? Или задуматься не медлить в этом случае?
1 ответ
Я протестировал производительность с отражением, и это похоже на упомянутое выше решение. Так что вот решение с отражением, если это кому-то нужно. Эта функция получает данные из БД и заполняет абстрактный массив
func GetItems(design string, viewName string, opts map[string]interface{}, arrayType interface{}) (interface{}, error) {
res := couchResponse{}
opts["limit"] = 100000
bytes, err := CouchView(design, viewName, opts)
if err != nil {
return nil, err
}
err = json.Unmarshal(bytes, &res)
if err != nil {
return nil, err
}
dataType := reflect.TypeOf(arrayType)
slice := reflect.MakeSlice(reflect.SliceOf(dataType), len(res.Rows), len(res.Rows))
for i := 0; i < len(res.Rows); i++ {
if opts["include_docs"] == true {
err = json.Unmarshal(res.Rows[i].Doc, slice.Index(i).Addr().Interface())
} else {
err = json.Unmarshal(res.Rows[i].Value, slice.Index(i).Addr().Interface())
}
if err != nil {
return nil, err
}
}
x := reflect.New(slice.Type())
x.Elem().Set(slice)
return x.Interface(), nil
}
и получение данных с помощью этой функции:
var e Event
res, err := GetItems("data", "data_list", map[string]interface{}{}, e)