产生原因
调用 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()