我正在使用 go-gorm 开发具有大量模型的 API。到目前为止,对于“GetAll”函数,我一直在使用以下(简化):
func GetAllUsers(w,r){
//... get params and do some check
pages := []*models.User{} //<-main problem I have to give the full type
models.GetDB().Model(&models.User{}).Offset(offset).Limit(pagesize).Find(&pages)
//do the http response(w,pages)
}
Run Code Online (Sandbox Code Playgroud)
但我想避免复制/粘贴函数来修改类型(这里是models.User)以从db获取所有模型。
我确实使用反射或界面尝试了不同的方法,但似乎没有一个像:
func GenericGetAll(w http.ResponseWriter, r *http.Request, data interface{}) {
dtype := reflect.TypeOf(data)
pages := reflect.New(reflect.SliceOf(dtype)).Elem().Interface()
log.Printf("%+v", pages)
//reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(data)), 0, 20)
//new([]gorm.Model)
GetDB().LogMode(true).Model(data).Offset(offset).Limit(pagesize).Find(&pages)
utils.Respond(w, pages)
}
Run Code Online (Sandbox Code Playgroud)
所以我可以直接在我的处理程序中使用它:
GenericGetAll(w,r,&models.User{}) for user
GenericGetAll(w,r,&models.Product{}) for Product
GenericGetAll(w,r,&models.Company{}) for Company
Run Code Online (Sandbox Code Playgroud)
这比仅仅为了修改类型而复制/粘贴另一个函数更干净......
但是使用这些不同的方法会产生问题:
我应该如何使用反射从函数的参数类型中获取切片?
这仅适用于 Golang 吗?我知道 golang 中不存在多态性,但是......这是一个必需的功能,或者有什么我不知道的关于 golang 的魔法?^^。
谢谢
我找到了解决方案!!
func GenericGetAll(w http.ResponseWriter, r *http.Request, data interface{}) {
dtype := reflect.TypeOf(data)
pages := reflect.New(reflect.SliceOf(dtype)).Interface()
offset, pagesize, order := GetAllFromDb(r)
err := error(nil)
if offset <= 0 && pagesize <= 0 {
err = errors.New(order)
}
if order != "" {
err = GetDB().LogMode(true).Model(data).Order(order).Offset(offset).Limit(pagesize).Find(pages).Error
} else {
err = GetDB().LogMode(true).Model(data).Offset(offset).Limit(pagesize).Find(pages).Error
}
if err != nil {
utils.Respond(w, utils.Message(false, fmt.Sprintf("Error while retrieving data")))
return
}
resp := utils.Message(true, "data returned")
resp["data"] = pages
utils.Respond(w, resp)
}
Run Code Online (Sandbox Code Playgroud)
而不是获取 Elem() 的接口
reflect.New(reflect.SliceOf(dtype)).Elem().Interface()
Run Code Online (Sandbox Code Playgroud)
其中返回[]*models.User
解决方案是直接使用 Interface :
pages := reflect.New(reflect.SliceOf(dtype)).Interface()
Run Code Online (Sandbox Code Playgroud)
哪个返回*[]*models.User被 gorm 的接口接受:)