reflect角度分析
没用过orm,但是我感觉可以从反射的角度解答下。
方法2res是空指针,res执行的地址是0为空,那么反射无法修改数据对象,那么用过下列四种方法初始化后均可以修改对象了;
-
res = &model.StProduct....
res给指针赋值了,指向了地址0xn,那么find(res)中res指针是有效的可以修改属性。
-
res = new(model)
res同样给指针初始化了不指向了0,所以也可以find(res)
-
var res model.StProduct...
,这样的res是一个结构体,&res得到的是一个指向res的指针,同样地址指向非空可设置。
-
var res *model.StProduct
,&res得到的二重指针,地址非空可设置。
gorm源码分析
https://github.com/jinzhu/gor...
判断了scope的value的reflec.Indirect(reflect.ValueOf(...)).Kind()的类型是否是Slice或Struct,但是空指针返回的kind为invalid,所以触发报错。
results = scope.IndirectValue()
// ...
if kind := results.Kind(); kind == reflect.Slice {
// ...
} else if kind != reflect.Struct {
scope.Err(errors.New("unsupported destination, should be slice or struct"))
return
}
scope部分实现的IndirectValue方法,等于 return reflec.Indirect(reflect.ValueOf((scope.Value))
。
// IndirectValue return scope's reflect value's indirect value
func (scope *Scope) IndirectValue() reflect.Value {
return indirect(reflect.ValueOf(scope.Value))
}
一个damo返回了空指针解除全部引用后的Kind。
https://play.golang.org/p/1ft...
package main
import (
"fmt"
"reflect"
)
func main() {
var i *int
fmt.Println(reflect.Indirect(reflect.ValueOf(i)).Kind())
fmt.Println("Hello, playground")
}
end
综上所述传入参数是空指针无法修改数据导致的报错。
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…