从数据库获取数据并填充数组的Golang抽象函数
Golang abstract function that gets data from db and fills array
我想创建一个抽象函数,它从数据库中获取数据并用这些数据填充数组。数组的类型可以不同。由于性能问题,我想在没有反映的情况下这样做。
我只想在任何地方调用一些函数,如 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
})
它可以工作,但是调用此函数的代码太多,而且将事件数组复制到接口数组时也存在一些性能问题。
没有reflect和短函数调用代码怎么办?还是反映这种情况不要慢?
我用reflect测试了性能,和上面提到的方案类似。所以如果有人需要的话,这里有反射的解决方案。该函数从数据库中获取数据并填充抽象数组
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)
我想创建一个抽象函数,它从数据库中获取数据并用这些数据填充数组。数组的类型可以不同。由于性能问题,我想在没有反映的情况下这样做。 我只想在任何地方调用一些函数,如 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
})
它可以工作,但是调用此函数的代码太多,而且将事件数组复制到接口数组时也存在一些性能问题。
没有reflect和短函数调用代码怎么办?还是反映这种情况不要慢?
我用reflect测试了性能,和上面提到的方案类似。所以如果有人需要的话,这里有反射的解决方案。该函数从数据库中获取数据并填充抽象数组
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)