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; ?>
】
相关推荐
- 如何使用正则表达式批量替换重复的“-”模式为固定字
- Mac系统更新下载慢或失败怎么办_解决macOS升
- 如何使用Golang实现基本类型比较_Golang
- 如何在Golang中使用内置函数_Golangle
- Win11怎么打开旧版计算器_Win11恢复传统计
- 如何在Golang中定义接口_抽象方法和多态实现
- Linux如何挂载新硬盘_Linux磁盘分区格式化
- 作用域操作符会影响性能吗_php静态调用性能分析【
- 如何使用Golang实现微服务状态监控_Golan
- 使用类变量定义字符串常量时如何实现类型安全的 Li
- Win11怎样安装搜狗输入法_Win11安装搜狗输
- 如何使用正则表达式提取以编号开头、后接多个注解的逻
- Windows10系统怎么查看设备管理器_Win1
- Go 中 defer 语句在 goroutine
- 如何使用Golang模拟请求超时_Golang c
- 如何使用Golang实现路由参数绑定_使用Mux和
- Windows10电脑怎么设置自动连接WiFi_W
- php怎么捕获异常_trycatch结构处理运行时
- 如何在Golang中实现WebSocket广播_使
- Windows怎样关闭开始菜单推荐广告_Windo
- c++协程和线程的区别 c++异步编程模型对比【核
- Go语言中slice追加操作的底层共享机制详解
- windows如何测试网速_windows系统网络
- c++ reinterpret_cast怎么用 c
- Win10如何卸载自带Edge_Win10彻底卸载
- Win11怎么用设置清理回收站_Win11设置清理
- 如何在JavaScript中动态拼接PHP的bas
- Win11如何连接Xbox手柄 Win11蓝牙连接
- 如何使用Golang encoding/json解
- 如何正确访问 Laravel 模型或对象的属性而非
- 如何在Golang中指定模块版本_使用go.mod
- 如何在Golang中处理JSON字段缺失_Gola
- win11 OneDrive怎么彻底关闭 Win1
- Win11怎么修改DNS服务器 Win11设置DN
- Windows如何查看和管理已安装的字体?(字体文
- Mac如何解压zip和rar文件?(推荐免费工具)
- Go语言中slice追加操作的底层共享机制解析
- Win11怎么关闭自动调节屏幕亮度_Windows
- php怎么下载安装后设置默认字符集_utf8配置步
- 跨文件调用类方法怎么用_php作用域操作符与自动加
- 如何使用Golang理解结构体指针方法接收者_Go
- Win11怎么清理C盘虚拟内存_Win11清理虚拟
- c++23 std::expected怎么用 c+
- 如何处理“XML格式不正确”错误 常见XML we
- Mac如何设置动态壁纸?(让桌面动起来)
- php删除数据怎么软删除_添加is_del字段标记
- c++中如何计算坐标系中两点间距离_c++勾股定理
- 如何在Golang中优化文件读写性能_使用缓冲和并
- Win10怎么卸载剪映_Win10彻底卸载剪映方法
- php订单日志怎么记录物流_php记录订单物流变更

QQ客服