Go 中通过 reflect.TypeOf(v).Kind() 获取变量底层类型类别,如 struct、slice、ptr、map 等,比 Name() 更可靠;结构体字段遍历需先判断 Kind 是否为 struct,再用 Field(i).Type.Kind() 判断各字段类型。

在 Go 中,可以通过 reflect.TypeOf 获取任意变量的类型信息,并进一步判断其具体类别(如结构体、切片、指针、map 等)。关键在于使用 reflect.Type.Kind() 方法——它返回的是底层基础类型类别,比 reflect.Type.Name() 或 String() 更可靠,尤其适用于接口、自定义类型或嵌套类型。
获取字段类型的基本步骤
要获取结构体字段的类型,需先通过 reflect.TypeOf 得到结构体类型的 reflect.Type,再用 Field(i) 取出字段,最后调用 Type.Kind() 判断类别:
- 对任意变量调用
reflect.TypeOf(v),得到reflect.Type - 若该类型是结构体,可用
t.NumField()和t.Field(i)遍历字段 - 每个
StructField的Type字段仍是reflect.Type,可继续调用.Kind() -
.Kind()返回reflect.Kind枚举值(如reflect.Struct、reflect.Slice),不依赖类型名
常用 Kind 值及对应判断示例
以下是最常用于字段类型识别的 Kind 类别,适合做分支处理:
-
struct:
t.Kind() == reflect.Struct→ 表示是结构体类型(含匿名字段) -
slice:
t.Kind() == reflect.Slice→ 如[]int、[]string -
ptr:
t.Kind() == reflect.Ptr→ 指针类型,可用t.Elem()获取所指类型 -
map:
t.Kind() == reflect.Map→ 如map[string]int -
interface:
t.Kind() == reflect.Interface→ 包括空接口interface{} -
string / int / bool 等基础类型:直接匹配
reflect.String、reflect.Int、reflect.Bool等
完整示例:遍历结构体字段并打印类型类别
下面是一个实用例子,展示如何解析结构体每个字段的 Kind:
立即学习“go语言免费学习笔记(深入)”;
type User struct {
Name string
Age int
Tags []string
Info *Info
Extra map[string]interface{}
}
type Info struct {
ID uint64
}
func printFieldKinds(v interface{}) {
t := reflect.TypeOf(v)
if t.Kind() == reflect.Ptr {
t = t.Elem() // 解引用指针,获取实际结构体类型
}
if t.Kind() != reflect.Struct {
fmt.Println("不是结构体类型")
return
}
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
kind := f.Type.Kind()
fmt.Printf("字段 %s: %s (Kind=%s)\n", f.Name, f.Type, kind)
}
}
// 调用示例
printFieldKinds(&User{})
输出类似:
字段 Name: string (Kind=string)
字段 Age: int (Kind=int)
字段 Tags: []string (Kind=slice)
字段 Info: *main.Info (Kind=ptr)
字段 Extra: map[string]interface {} (Kind=map)
注意:Kind 与 Name 的区别
Kind() 描述的是底层类型分类,而 Name() 只返回命名类型的名字(对匿名类型或内建类型返回空字符串):
-
type MyInt int→t.Kind()是reflect.Int,t.Name()是"MyInt" -
[]byte→t.Kind()是reflect.Slice,t.Name()是""(无名称) -
interface{}→t.Kind()是reflect.Interface,t.Name()是""
因此,做类型分支判断时应优先用 Kind(),而非依赖 Name() 或 String()。










