reflect.typeof()用于获取变量运行时类型,返回reflect.type对象;需注意传值非指针、nil接口会panic;name()返回包内名(内置类型为空),string()返回全限定名;kind()返回底层分类更稳定可靠;反射性能低且信息有限,应慎用。

用 reflect.TypeOf() 获取变量的运行时类型
Go 的类型信息在编译期确定,但若需在运行时判断变量具体是什么类型(比如处理 interface{} 或泛型擦除后的值),必须用反射。最直接的方式是调用 reflect.TypeOf(),它返回一个 reflect.Type 对象。
注意:传入的是值本身,不是指针(除非你明确想获取指针类型);如果传 &v,得到的是 *T 类型,不是 T。
-
reflect.TypeOf(42)→ 返回int类型对象 -
reflect.TypeOf(&42)→ 返回*int类型对象 - 对
nil接口变量调用会 panic,务必先判空或确保非 nil
用 Type.Name() 和 Type.String() 区分包内名与全限定名
拿到 reflect.Type 后,Name() 只返回类型在定义包内的名字(如 "MyStruct"),对内置类型(int、string)或未导出类型返回空字符串;而 String() 返回完整可读描述(如 "main.MyStruct" 或 "int")。
常见误用:仅依赖 Name() 判断类型,结果对 int、[]byte、map[string]int 等都返回空,导致逻辑失效。
立即学习“go语言免费学习笔记(深入)”;
- 需要做类型分支匹配时,优先用
type switch或reflect.Type.Kind() - 仅当需打印或日志记录时,用
String()更稳妥 - 自定义结构体若在其他包定义,
Name()仍只返回结构体名,不含包路径
用 reflect.ValueOf().Kind() 判断底层类型分类
Kind() 比 Name() 更底层、更稳定,它返回的是 reflect.Kind 枚举值(如 reflect.Struct、reflect.Slice、reflect.Ptr),不依赖包名或是否导出,适合做类型归类处理。
例如解析 JSON 通用数据时,你并不关心字段叫什么,只关心它是对象、数组还是字符串——这时 Kind() 是唯一可靠依据。
-
reflect.TypeOf([]int{}).Name()→""(切片无名字) -
reflect.TypeOf([]int{}).Kind()→reflect.Slice - 对指针解引用后调用
Kind()才能得到目标类型,否则始终是reflect.Ptr - 注意
Kind()不等价于语言关键字:比如type MyInt int的Kind()是reflect.Int,不是reflect.Int64
反射获取类型信息的性能与安全边界
反射是 Go 中明确的性能敏感操作:每次 reflect.TypeOf() 或 reflect.ValueOf() 都涉及接口转换和类型擦除逆向推导,比直接类型断言慢一个数量级以上。线上高频路径应避免反射取类型名。
更隐蔽的问题是类型信息丢失:函数参数若声明为 interface{},反射只能看到实际值的类型,无法还原原始变量名、注释、tag 含义等上下文。
- 调试或配置解析场景可用,业务核心逻辑尽量用类型断言或泛型约束替代
- 对结构体字段遍历时,
reflect.StructField.Type.Name()对匿名字段可能为空,需结合Anonymous字段判断 - 跨模块传递反射对象时,注意
reflect.Type不满足==比较,要用reflect.Type.AssignableTo()或ConvertibleTo()做安全校验
unsafe 或 cgo),这部分信息就不可靠了。










