json:"-"仅对首字母大写的导出字段生效,小写字段因不可导出而被json.marshal静默忽略,根本不会进入序列化流程;标签格式必须严格为json:"-",含空格或错误语法将失效。

json:"-" 会彻底跳过字段,但字段必须可导出
直接写 json:"-" 是最常用的忽略方式,但它只对首字母大写的导出字段生效。比如 type User struct { Password string `json:"-"` } 能成功隐藏;但若写成 password string `json:"-"`,序列化结果仍是空对象 {}——因为小写字段根本进不了 json.Marshal 的扫描范围。
常见错误包括:
- 字段名用小写,却以为加了
json:"-"就安全了 - 标签写成
json:"_"或json:"",实际无效 -
json:"name, omitempty"中逗号后带空格,Go 会静默截断为json:"name,",导致字段名变成字面量name,
omitempty 不是“按需隐藏”,它只认零值
omitempty 的触发条件很明确:字段值等于其类型的零值(""、0、false、nil)。但它对指针类型容易误判——*string 指向一个空字符串 "",这个指针本身非 nil,所以不会被 omit。
使用时要注意:
- 想靠
omitempty隐藏敏感字段?不行。它不处理权限逻辑,只响应值是否为零 - 时间字段用
time.Time类型时,零值是0001-01-01T00:00:00Z,不是nil,所以omitempty对未赋值的time.Time也无效 - 嵌套结构体字段若本身是零值,且外层字段已导出,
omitempty才会起作用
json 和 xml 标签可以共存,但不能混用语义
同一个字段可以同时声明 json 和 xml 标签,比如 Name string `json:"user_name" xml:"UserName"`,两者互不干扰。标准库只读取自己关心的 key,encoding/json 完全忽略 xml 部分。
但要注意:
- 别把
xml:"attr"这类 XML 特有选项塞进json标签里,Go 不报错,但json.Marshal不识别,可能造成字段名意外变成attr - 如果字段要同时支持 JSON 和 XML 输出,建议显式写出两个标签,不要依赖自动转换
-
omitempty在 JSON 和 XML 中行为一致,但 XML 的attr模式下不支持omitempty
gorm 标签和 json 标签完全无关,别指望它们共享配置
很多人误以为 json:"user_name" 也能让 GORM 把字段映射到数据库 user_name 列——不会。GORM 只看 gorm 标签,比如 gorm:"column:user_name"。两个标签必须并列存在,且各自完整。
典型疏漏点:
- 只写了
json:"user_name" gorm:"column:user_name",但漏了主键声明gorm:"primaryKey",导致迁移时没建主键 - 时间字段同时用于 JSON 输出和 DB 写入,却只在
json标签里写了created_at,GORM 侧没配autoCreateTime,造成字段名不一致或时间不自动填充 - 用
gorm:"type:varchar(255)"控制数据库类型,但没同步考虑 JSON 序列化时是否需要omitempty或重命名
多标签结构体一旦变复杂,最容易被忽略的是字段可见性与标签语义边界的混淆——导出性决定能否进序列化流程,而每个标签的 key 决定谁来读它。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











