产生原因
调用 FieldByName()
方法时,调用者与预期类型不相符。
// 错误代码
func setNewArticleInfoToCache(article *Article) {
fields := []string{
"Title", "Abstract", "ID", "AuthorID", "CreateTime",
}
immutable := reflect.ValueOf(article)
// immutable := reflect.ValueOf(article).Elem()
for _, field := range fields {
val := immutable.FieldByName(field)
fmt.Println(val)
}
}
//panic: reflect: call of reflect.Value.FieldByName on ptr Value [recovered]
// panic: reflect: call of reflect.Value.FieldByName on ptr Value
由于传递给reflect.ValueOf
的 article
是一个指针,所以得到的immutable
的类型是Ptr
, 而FieldByName
方法需要调用者类型为Struct
:
func (v Value) FieldByName(name string) Value {
// 必须是 Struct 类型
v.mustBe(Struct)
if f, ok := v.typ.FieldByName(name); ok {
return v.FieldByIndex(f.Index)
}
return Value{}
}
func (f flag) mustBe(expected Kind) {
if Kind(f&flagKindMask) != expected {
// 此处抛出的异常
panic(&ValueError{methodName(), f.kind()})
}
}
解决办法
ValueOf()
直接传入结构体- 使用
Elem()
获取指针指向的元素Value
immutable := reflect.ValueOf(article).Elem()