gorm如何使用反射类型来泛化一个api函数

LZR*_*LZR 5 go go-gorm

我正在使用 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)

这比仅仅为了修改类型而复制/粘贴另一个函数更干净......

但是使用这些不同的方法会产生问题:

  • []*interface{},我丢失了表名并得到一个 sql 错误,因为表名 '' 不存在
  • new([]gorm.Model) 它失去了我的表名并使用 gorm.model 默认表名:/
  • reflect.New(reflect.SliceOf(dtype)).Elem().Interface() 和我得到一个错误:不支持的目标,应该是切片或结构,即使它确实创建了切片:/ log.printf() 给出一个空大批 []

我应该如何使用反射从函数的参数类型中获取切片?

这仅适用于 Golang 吗?我知道 golang 中不存在多态性,但是......这是一个必需的功能,或者有什么我不知道的关于 golang 的魔法?^^。

谢谢

LZR*_*LZR 5

我找到了解决方案!!

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 的接口接受:)