Go语言反射获取结构体字段_Golang struct反射示例
技术百科
P粉602998670
发布时间:2026-01-27
浏览: 次 要获取结构体字段名、类型、值,须先用 reflect.TypeOf 获取类型信息,再用 reflect.ValueOf 获取值信息;遍历字段需基于 Value 的 NumField/Field 方法,且传入值必须为导出结构体(非指针或先 Elem 解引用),字段需导出才能访问值与 tag,修改值前须确保 Value 可寻址且可设置,反射性能低,不宜用于热路径。
用 reflect.TypeOf 和 reflect.ValueOf 获取结构体字段信息
Go 反射要拿到结构体字段名、类型、值,必须先用 reflect.TypeOf 拿类型信息,再用 reflect.ValueOf 拿值信息。两者不能混用:前者返回 reflect.Type,后者返回 reflect.Value,字段遍历必须基于 Value 的 NumField/Field 方法。
常见错误是直接对指针类型调 NumField,结果 panic:panic: reflect: NumField of non-struct type —— 因为 *T 是指针类型,不是 struct 类型。
- 确保传入的是结构体值(非指针),或先用
.Elem()解引用 - 字段必须是导出的(首字母大写),否则
Field返回零值且不可设 -
reflect.TypeOf(x).Name()对匿名结构体返回空字符串,需用.String()看完整类型描述
遍历字段时正确处理导出性与标签(tag)
反射无法访问未导出字段(小写开头),这是 Go 的语言限制,不是反射 API 的 bug。想读取 tag(如 json:"name"),要用 StructField.Tag.Get("json"),但前提是该字段已导出。
注意 Tag 是字符串,解析靠自己;标准库用 r 提供 
Get 方法,但不自动处理 quote 或空格——比如 `json:"user_name,omitempty"` 中的 omitempty 需手动切分。
- 用
field.Type.Kind() == reflect.Struct判断是否嵌套结构体,再递归处理 - 标签值里带空格或逗号时,
Tag.Get("json")返回完整字符串,别直接当布尔用 - 如果结构体字段是接口类型(
interface{}),field.Type是interface{},但field.Interface()才是真实值
修改字段值必须传地址且字段可寻址
用反射改结构体字段值,reflect.Value 必须是可寻址的(CanAddr() == true),通常意味着原始变量得是指针,且字段本身导出。否则调 SetXxx 会 panic:reflect: reflect.Value.SetString using unaddressable value。
典型错误写法:
type User struct { Name string }
u := User{"Alice"}
v := reflect.ValueOf(u).FieldByName("Name")
v.SetString("Bob") // panic!
正确做法:
u := &User{"Alice"}
v := reflect.ValueOf(u).Elem().FieldByName("Name")
if v.CanSet() {
v.SetString("Bob")
}
-
reflect.ValueOf(u).Elem()是关键:先取指针指向的值,才能寻址 - 永远在
SetXxx前检查CanSet(),它比CanAddr()更严格(还要求字段导出) - 对 int/float 等基本类型,用
SetInt/SetFloat64,别用Set传 interface{}
性能和适用边界:别在热路径用反射遍历结构体
反射比直接字段访问慢 10–100 倍,且编译器无法内联或优化。日常序列化(如 JSON)、ORM 映射、配置绑定等场景合理,但高频循环里逐字段反射读写就是反模式。
容易被忽略的一点:反射无法获取字段定义顺序以外的信息,比如 struct 字面量里的注释、默认值、是否必填——这些只能靠额外标记(如自定义 tag)或代码生成补足。
如果项目中大量出现 reflect.Value.FieldByName,建议评估是否该用 code generation(如 stringer 或自定义 go:generate 工具)预生成类型安全的访问函数。
# go语言
# 工具
# js
# json
# go
# golang
# 循环
# 递归
# String
# int
# 标准库
# 指针
# 字符串
# 接口
# Interface
# 结构体
# Struct
# 指针类型
# Float
# using
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Windows怎样关闭开始菜单广告_Windows
- windows如何备份注册表_windows导出和
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- Win10怎么关闭自动更新错误弹窗_Win10策略
- Win11怎么设置触控板手势_Windows11三
- Win10如何卸载Skype_Win10卸载Sky
- 如何理解Go指针和内存分配关系_Go Pointe
- 如何在 Go 中比较自定义的数组类型(如 [20]
- Win11如何更改用户账户文件夹名称 Win11修
- Windows11怎么自定义任务栏_Windows
- 如何在Golang中使用内置函数_Golangle
- php订单日志怎么记录物流_php记录订单物流变更
- Win11怎样彻底卸载自带应用_Win11彻底卸载
- Linux如何安装Golang环境_Linux下G
- Win11怎么更改任务栏位置_修改注册表将Win1
- Win11怎么设置默认邮件应用_Windows11
- WindowsUSB驱动安装异常怎么办_USB驱动
- Windows蓝屏BAD_POOL_HEADER故
- Windows 11怎么设置默认解压软件_Wind
- Python邮件系统自动化教程_批量发送解析与模板
- Win11怎么设置按流量计费_Win11限制后台流
- php485能和物联网模块通信吗_php485对接
- Linux怎么设置磁盘配额_Linux系统Quot
- MySQL 中使用 IF 和 CASE 实现查询字
- Win11搜索栏无法输入_解决Win11开始菜单搜
- Win11怎么设置闹钟_Windows 11时钟应
- Win10如何备份驱动程序_Win10驱动备份步骤
- 如何在 ACF 中正确更新嵌套多层 Group 字
- ACF 教程:如何正确更新嵌套在多层 Group
- Windows10系统怎么查看系统版本_Win10
- LINUX怎么进行文本内容搜索_Linux gre
- Win11如何设置ipv6 Win11开启IPv6
- Win11怎么设置指纹解锁 Win11笔记本录入指
- Mac如何使用听写功能_Mac语音输入打字【效率技
- C++如何使用Qt创建第一个GUI窗口?(入门教程
- Win11如何设置自动关机 Win11定时关机命令
- Windows10系统怎么查看显卡驱动_Win10
- 如何使用Golang table-driven基准
- Linux怎么禁止Root用户远程登录_Linux
- 微信企业付款回调PHP怎么接收_处理企业付款异步通
- 如何优化Golang内存分配与GC调度_Golan
- Win11怎样安装企业微信_Win11安装企业微信
- php串口通信波特率怎么选_根据硬件手册设置正确波
- 作用域操作符会影响性能吗_php静态调用性能分析【
- C++如何使用std::optional?(处理可
- C#如何在一个XML文件中查找并替换文本内容
- Win11怎么设置开机问候语_自定义Win11锁屏
- 如何在Golang中处理模块冲突_解决依赖版本不兼
- Win11怎么更改默认打开方式_Win11关联文件
- 如何在Golang中实现文件下载_Golang文件

QQ客服