GORM不使用数据绑定获取任意SQL获取结果
GORM不使用数据绑定获取任意SQL获取结果
在gorm中,想获取sql执行的结果,必须将返回结果绑定到slice或者struct中,但是如果我们想通用执行任意语句,在事先不知道表结构的情况下是没办法使用这个方式的,最后通过查阅资料发现一个曲线救国的方式
rows, err := db.Raw(sql).Rows()
if err != nil {
result = append(result, err.Error())
return result
}
var colums []string
for rows.Next() {
//先获取所有的column
if colums == nil {
colums, _ = rows.Columns()
}
result = append(result, colums)
//建立俩个interface数组,columnPointers中存在columns的地址
columns := make([]interface{}, len(colums))
columnPointers := make([]interface{}, len(colums))
for i, _ := range columns {
//赋值地址
columnPointers[i] = &columns[i]
}
//扫描结果
rows.Scan(columnPointers...)
m := make(map[string]interface{})
for i, colName := range colums {
val := columnPointers[i].(*interface{})
m[colName] = *val
}
//log.Println(m)
result = append(result, m)
//result = append(result, row)
}
return result
//log.Println(result)
}
一开始不太好理解,然后去看了gorm Scan部分的代码
sql/sql.go
func (rs *Rows) Scan(dest ...interface{}) error {
rs.closemu.RLock()
...一些不重要的代码...
for i, sv := range rs.lastcols {
//重点看convertAssignRows,是如何赋值的
err := convertAssignRows(dest[i], sv, rs)
if err != nil {
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %v`, i, rs.rowsi.Columns()[i], err)
}
}
return nil
}
func convertAssignRows(dest, src interface{}, rows *Rows) error {
// 通过反射找到具体类型
var sv reflect.Value
switch d := dest.(type) {
//字符串指针
case *string:
.....
case *[]byte:
.....
case *RawBytes:
......
case *bool:
.....
//就是这里了,我们传进来的是指向columns的interface的指针,所以直接给columns的值修改了
case *interface{}:
*d = src
return nil
}
...一些不相关的代码...
}