go反射仅适用于动态处理未知结构的场景,如配置绑定、orm映射等;使用reflect.typeof和reflect.valueof前须确保非nil且可寻址,优先用.kind()判型,取字段标签需从type获取,调用方法需导出且接收器匹配,所有反射操作必须配合运行时校验与测试。

Go反射只在真正需要动态处理未知结构时才值得用,比如配置绑定、ORM映射、通用序列化框架——它不是泛型的替代品,也不是写业务逻辑的常规工具。
什么时候该用 reflect.TypeOf 和 reflect.ValueOf?
当你手头只有一个 interface{},但必须在运行时判断它到底是不是 []string、map[string]interface{} 或自定义 struct,并据此分支处理时,才用这两个函数。
- 优先调用
.Kind()而不是.String()判类型:前者返回reflect.Struct这类稳定枚举,后者含包路径(如"main.User"),一换包名就失效 -
reflect.TypeOf(nil)返回nil,不判空直接调.Kind()会 panic - 想取指针指向的类型?得链式调用:
reflect.TypeOf(&x).Elem().Kind(),漏掉Elem()就拿到reflect.Ptr而非真实类型
为什么给结构体字段赋值必须传指针并检查 CanSet()?
因为 Go 反射严格遵循导出规则和可寻址性——字段首字母小写、传的是 struct 值而非指针、或没解引用,都会让 FieldByName 返回只读 Value,SetString() 直接 panic。
- 必须:
reflect.ValueOf(&u).Elem().FieldByName("Name"),不能是reflect.ValueOf(u) - 赋值前必加
if f.CanSet() { f.SetString(...) },否则 runtime error: “cannot set unaddressable value” - 字段标签(如
json:"user_name")要从reflect.Type上取:reflect.TypeOf(u).FieldByName("Name").Tag.Get("json"),reflect.Value上没有Tag方法
调用方法时为什么 MethodByName 总是失败?
常见原因就两个:方法未导出(首字母小写),或接收器类型不匹配(值接收器 vs 指针接收器)。反射不会帮你自动解引用或取地址。
立即学习“go语言免费学习笔记(深入)”;
- 只有导出方法(
func (u User) GetName())能被MethodByName找到,func (u User) getName()查不到 - 若方法定义为指针接收器(
func (u *User) Save()),你必须传&u给reflect.ValueOf(),否则Call()会 panic - 参数类型必须严格匹配:传
[]reflect.Value{reflect.ValueOf("id")},不能传string原值
最常被忽略的一点:反射代码一旦写错,错误全在运行时暴露——编译器不报任何问题。一个拼错的字段名、少写的 Elem()、漏判的 CanSet(),都得等服务跑起来、特定请求进来才触发 panic。所以,凡用反射的地方,务必配上类型校验、空值防护和单元测试覆盖边界 case。










