应使用 reflect.typeof(v).kind() 判断底层类型,而非直接比较;对 interface{} 优先用类型断言;reflect.typeof(nil) 返回 nil,需先判空;结构体字段类型需通过 t.field(i).type 获取。

用 reflect.TypeOf 获取变量具体类型,但别直接比较返回值
Go 的 reflect.TypeOf 返回的是 reflect.Type 类型,不是字符串或基础类型名。常见错误是写 if reflect.TypeOf(v) == "string" —— 这会编译失败,因为类型不匹配。
正确做法是用 .Name() 或 .Kind() 提取信息:
-
.Name()返回类型在定义包中的名字(对内建类型如string、int返回空字符串) -
.Kind()返回底层类型分类(reflect.String、reflect.Struct等),更稳定,推荐用于判断 - 如果要区分自定义类型(比如
type MyStr string),得用.Name()+.PkgPath()联合判断
示例:
var s string = "hello" t := reflect.TypeOf(s) fmt.Println(t.Kind()) // 输出:<code>String</code> fmt.Println(t.Name()) // 输出:<code>""</code>(空字符串) fmt.Println(t.PkgPath()) // 输出:<code>""</code>
判断 interface{} 里装的是什么类型,优先用类型断言而非反射
多数场景下,你拿到的是 interface{}(比如函数参数、map 值、JSON 解析结果),这时 reflect.TypeOf 是“能用”,但不是“该用”。类型断言更轻量、更安全、更易读。
立即学习“go语言免费学习笔记(深入)”;
- 用
v, ok := x.(string)判断并提取,ok 为 true 才真正是 string - 用
switch v := x.(type)处理多种可能类型,比嵌套 if + reflect 更清晰 - 只有在类型列表未知、需遍历字段、或处理泛型擦除后类型时,才需要
reflect - 反射有运行时开销,且绕过编译器类型检查,容易掩盖逻辑错误
反例(不必要用反射):
func handle(v interface{}) {
if reflect.TypeOf(v).Kind() == reflect.String { /* ... */ } // ❌
}
// ✅ 改成:
func handle(v interface{}) {
if s, ok := v.(string); ok { /* ... */ }
}
reflect.TypeOf(nil) 返回 nil,不是你想的任何类型
这是最常踩的坑:对 nil 指针、nil slice、nil map 调用 reflect.TypeOf,结果是 nil,不是 reflect.Ptr 或 reflect.Slice。
-
var p *string; reflect.TypeOf(p)→nil(不是*string) -
var s []int; reflect.TypeOf(s)→nil(不是[]int) - 必须先确保值非 nil,再反射;或改用
reflect.ValueOf(x).Kind(),它对 nil 值仍返回对应 kind(如Ptr、Slice) - 注意:
reflect.ValueOf(nil).Kind()会 panic,得先!reflect.ValueOf(x).IsNil()判断
安全写法:
v := reflect.ValueOf(x)
if v.Kind() == reflect.Ptr && v.IsNil() {
// x 是 nil 指针
} else if v.Kind() == reflect.Ptr {
t := v.Type().Elem() // 才能拿到 *T 的 T
}结构体字段类型判断要用 reflect.Value.Field(i).Type(),不是 reflect.TypeOf(struct).Field(i)
想动态读一个 struct 字段的类型?别直接对 struct 类型调 .Field(i) —— 那返回的是 reflect.StructField,里面 Type 字段才是你要的类型描述符。
-
reflect.TypeOf(myStruct).Field(0).Type是字段的类型(reflect.Type),可继续调.Kind() - 如果字段是嵌套 struct 或指针,
.Type.Elem()或.Type.Elem().Field(0).Type可逐层取 - 注意导出限制:
reflect.Value.Field(i)只能访问导出字段(首字母大写),否则 panic - 用
reflect.ValueOf(&myStruct).Elem()先取地址再解引用,才能安全读字段值
示例:
type User struct { Name string; Age int }
u := User{"Alice", 30}
t := reflect.TypeOf(u)
fieldType := t.Field(0).Type // <code>string</code>
fmt.Println(fieldType.Kind()) // <code>String</code>类型判断本身不难,难的是什么时候不该用反射——尤其是面对 interface{} 和 nil 值时,稍不注意就 panic 或逻辑错位。把类型断言和 reflect.Value 的生命周期(nil 判断时机、是否导出)理清楚,比记住所有 API 更重要。










