Go反射修改字段需三步:IsValid()→CanSet()→SetXxx();必须传指针、字段导出、检查可设置性,否则panic或静默失败;安全赋值需用tag匹配、类型转换;reflect.New()仅用于编译期未知类型。
Go 反射不能修改未导出字段,哪怕你拿到 reflect.Value —— 这是绝大多数 panic 和静默失败的根源。
为什么 v.FieldByName("Name").SetString("x") 总 panic?
常见错误现象:panic: reflect: cannot set 或值没变但也不报错。根本原因只有两个:
- 传入的不是指针:必须用
reflect.ValueOf(&u).Elem(),而不是reflect.ValueOf(u); - 字段未导出:
Name合法,name不合法 ——FieldByName对小写字段返回零值reflect.Value,CanSet()恒为false; - 没检查
CanSet()就调用SetString():未导出字段调用它不会 panic,但完全无效,极易误判逻辑正确。
正确姿势永远三步走:IsValid() → CanSet() → 再 SetXxx()。
怎么安全地从 map[string]interface{} 自动赋值到结构体?
这是 ORM、JSON 解析、配置加载的共性需求。核心不是“能不能做”,而是“怎么防崩”: