
go 的 `json.unmarshal` 要求结构体字段首字母大写(即导出字段),否则无法访问,导致反序列化静默失败(字段保持零值)。这是初学者最常遇到的陷阱之一。
在 Go 语言中,encoding/json 包仅能对导出字段(exported fields) 进行序列化与反序列化操作。所谓“导出字段”,是指字段名以大写字母开头的字段;而小写开头的字段(如 code、clientId)属于未导出字段(unexported),json 包无权读写,因此 json.Unmarshal 会跳过它们——既不报错,也不赋值,最终结构体字段维持其零值(如空字符串 ""),造成“解码不生效”的假象。
以下是你原始代码的问题复现与修复对比:
❌ 错误写法(字段未导出,反序列化无效):
type GOOGLE_JSON struct {
code string `json:"code"` // 小写 → 未导出 → 忽略
clientId string `json:"clientId"` // 小写 → 未导出 → 忽略
redirectUri string `json:"redirectUri"` // 小写 → 未导出 → 忽略
}运行后输出:{ }(全部为空字符串),且 err == nil,极易误导排查。
✅ 正确写法(首字母大写,显式导出):
type GOOGLE_JSON struct {
Code string `json:"code"`
ClientId string `json:"clientId"`
RedirectUri string `json:"redirectUri"`
}此时 json.Unmarshal 可正常映射,输出为:{111 222 333}。
? 补充说明与最佳实践:
- JSON tag(如 `json:"code"`)仅指定 JSON 键名映射关系,不能绕过导出规则;
- 字段名大小写需同时满足:① 首字母大写(导出) + ② tag 值与 JSON 字段名一致(区分大小写);
- 推荐使用 Go 官方风格:结构体字段名采用 PascalCase(如 ClientID),并配合清晰的 JSON tag(如 `json:"client_id"`)以兼顾可读性与规范性;
- 开发时建议始终检查 err 并启用 fmt.Printf("%+v", v) 输出结构体字段值,便于快速识别零值字段;
- 若需兼容私有字段逻辑,应改用自定义 UnmarshalJSON 方法,而非依赖默认行为。
记住这个黄金法则:Go 的 JSON 处理只认“大写的字段”——不是 JSON 标签,也不是注释,而是字段名本身是否导出。










