reflect.TypeOf() 直接传入变量返回其完整类型信息:reflect.TypeOf(42) 得 int,reflect.TypeOf(&x) 得 *int;注意勿混淆指针与基础类型,结构体字段需先取地址再用 reflect.ValueOf().Elem() 获取实际类型。

怎么用 reflect.TypeOf() 拿到变量的类型信息
直接调用 reflect.TypeOf() 是最常用方式,它返回一个 reflect.Type 接口值。注意:传入的是变量本身(不是指针),但返回的类型信息包含是否为指针、是否为切片等完整描述。
常见错误是传了指针却误以为得到的是基础类型——比如 reflect.TypeOf(&x) 返回的是 *int 类型,不是 int。
- 对基础类型:
reflect.TypeOf(42)→int - 对指针:
reflect.TypeOf(&x)→*int - 对结构体字段:需先取地址再用
reflect.ValueOf().Elem(),否则TypeOf()只能看到reflect.Value类型
reflect.Type 常用方法有哪些
拿到 reflect.Type 后,真正有用的是它的方法,而不是类型名字符串。别只盯着 Name() 或
看,它们在匿名类型、指针、接口上表现不一致。
Kind() 才是核心判断依据:返回reflect.Int、reflect.Struct、reflect.Ptr等底层种类,和具体名字无关Elem()用于解包:对切片、映射、通道、指针类型必须先调用它才能拿到元素/指向的类型Field(i)和NumField()仅对Kind() == reflect.Struct有效,否则 panicPkgPath()返回包路径,空字符串表示是内置类型或未导出类型(这时Name()也可能为空)为什么
reflect.TypeOf(x).Name()有时返回空字符串这是最容易困惑的点:
Name()只返回**命名类型**的名字,对匿名结构体、切片、指针、接口等一律返回空。比如[]string、map[int]bool、struct{X int}都没有名字。立即学习“go语言免费学习笔记(深入)”;
正确做法是结合
Kind()和Elem()/Key()/Out()等方法还原类型结构:-
t.Kind() == reflect.Slice→ 它是切片,再用t.Elem().Name()看元素是否是命名类型 -
t.Kind() == reflect.Map→ 用t.Key()和t.Elem()分别获取键/值类型 -
t.Kind() == reflect.Func→ 用t.NumIn()/t.NumOut()配合In(i)/Out(i)查参数返回值
反射获取类型时性能与安全要注意什么
反射不是零成本操作:
reflect.TypeOf()和reflect.ValueOf()都涉及接口转换和运行时类型检查,频繁调用会影响性能。尤其在 hot path(如 HTTP handler 内部)中应避免。更隐蔽的问题是类型断言失败或非法操作导致 panic:
- 对 nil 接口调用
reflect.ValueOf().Interface()会 panic - 对不可寻址的
reflect.Value调用Addr()或Set*方法会 panic - 用
reflect.Value.FieldByName()访问未导出字段,返回 zero value 且CanInterface()为 false
实际编码中,优先用类型断言或类型 switch 处理已知有限类型;反射只留给真正需要泛化处理的场景,比如序列化框架、ORM 字段扫描、测试工具里的 deep equal 判断。










