必须用 reflect.TypeOf 获取字段名、类型、标签,用 reflect.ValueOf(&s).Elem() 获取可寻址值以读写字段;私有字段无法通过反射访问;StructTag 解析需注意空值与拼写;高频场景应缓存 Type 避免重复反射。
reflect.TypeOf 和 reflect.ValueOf 获取结构体字段基本信息必须先区分类型信息和值信息:获取字段名、类型、标签要用 reflect.TypeOf;读写字段值则必须用 reflect.ValueOf,且该值需为可寻址(&struct{})才能修改。
reflect.TypeOf(v).Kind() 返回 reflect.Struct 才能继续调用 NumField()
reflect.ValueOf(s) 得到的是不可寻址的副本,CanSet() 为 false
reflect.ValueOf(&s),再用 .Elem() 取到结构体值type User struct {
Name string `json:"name" validate:"required"`
Age int `json:"age"`
}
u := User{Name: "Alice", Age: 30}
t := reflect.TypeOf(u) // 获取 Type
v := reflect.ValueOf(&u).Elem() // 获取可修改的 Value
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
fmt.Printf("字段名: %s, 类型: %s, JSON标签: %s\n",
f.Name, f.Type, f.Tag.Get("json"))
}
FieldByName 找不到私有字段?Go 的反射严格遵循导出规则:只有首字母大写的字段才是导出字段,FieldByName 和 FieldByNameFunc 均无法访问小写开头的字段,无论是否通过指针传入。
&struct{ name string },v.FieldByName("name") 返回零值,IsValid() 为 false
unsafe 操作内存属于未定义行为,生产环境禁用GetXXX() 方法或使用接口抽象StructTag 解析常见错误:空字符串、拼写错误与嵌套标签f.Tag.Get("json") 返回空字符串不等于标签不存在,可能只是该 key 对应值为空(如 json:""),也可能是 key 拼写错误(如写成 "JSON")。

`json:"name,omitempty" db:"name"` ✅,`json:"name, omitempty"` ❌
reflect.StructTag 可安全解析:tag := f.Tag; jsonTag := tag.Get("json"),无需手动切分reflect.TypeOf
reflect.TypeOf 和 reflect.ValueOf 是运行时开销较大的操作,尤其在高频路径(如 HTTP 中间件、序列化循环)中重复调用会显著拖慢性能。
reflect.Type 和字段索引映射,例如用 sync.Map 或全局变量初始化一次t := reflect.TypeOf(req); for i := 0; i
go:generate + stringer 或自定义模板),完全规避反射字段反射不是黑魔法,它把编译期确定的事推到运行时——代价就是慢、难调试、易出错。真正需要动态处理结构体时,先确认是否真的不能用接口、泛型或代码生成解决。