必须传入结构体指针并调用Elem()获取可寻址值,字段需导出且类型匹配才能安全Set;推荐用StructTag替代硬编码字段名。
用 reflect.Value.Set() 给结构体字段赋值前必须确保可寻址
直接对结构体字面量或非指针变量调用 reflect.ValueOf().FieldByName().Set() 会 panic,错误信息通常是 reflect.Value.Set using unaddressable value。这是因为反射无法修改不可寻址的值(比如栈上拷贝的 struct 值)。
正确做法是传入结构体指针,并用 reflect.Value.Elem() 获取其指向的可寻址值:
type User struct {
Name string
Age int
}
u := &User{}
v := reflect.ValueOf(u).Elem() // 必须 .Elem() 才能 Set
v.FieldByName("Name").SetString("Alice")
v.FieldByName("Age").SetInt(30)
- 如果传的是
reflect.ValueOf(User{}),后续任何Set*都会失败 -
reflect.ValueOf(&u).Elem()和reflect.ValueOf(u)效果等价(前提是 u 是指针),但前者更显式 - 字段必须是导出的(首字母大写),否则
FieldByName()返回零值,Set*会 panic
reflect.Value.SetString() 等类型专用方法只接受对应底层类型
不能混用:给 int 字段调用 SetString() 会 panic,错误信息类似 reflect.Value.SetString using value obtained using unexported field(实际更可能是 can't call SetString on int Value)。必须匹配字段的实际类型。
安全做法是先检查字段类型再调用对应方法: