json.unmarshal 返回 nil 表示解析成功,实际数据已写入传入的指针变量(如 &p);必须传地址而非值,因 go 是值传递,传值会导致静默失败(字段全为零值);结构体字段须大写导出并配 json:"key" 标签才能被正确赋值。

json.Unmarshal 不是“反向方法”,它就是 Go 标准库中专用于 JSON 反序列化的函数——没有所谓“正向/反向”的抽象命名,只有明确的用途:把 []byte 解析进你给的变量地址里。
为什么传 &p 而不是 p
Go 是值传递语言。json.Unmarshal 必须能修改你传入的变量内容,所以必须传指针。传 p 时,函数内部操作的是副本,原结构体字段全保持零值(""、0、nil),但编译不报错,错误静默。
- 正确:
err := json.Unmarshal(data, &p) - 错误:
err := json.Unmarshal(data, p)(语法合法,逻辑失效) - 切片同理:
var users []User; json.Unmarshal(data, &users)
结构体字段为啥必须大写 + json:"xxx" 标签
小写字母开头的字段(如 name string)不可导出,json 包完全忽略——不报错、不赋值、不警告。标签 json:"name" 是告诉解析器:“这个 JSON key 对应我这个字段”,且优先级高于字段名本身。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 字段名
Name+ 标签json:"user_name"→ 接收{"user_name":"alice"} - 字段名
CreatedAt+ 标签json:"created_at"→ 兼容常见 API 风格 - 嵌套结构体内字段同样要大写 + 合理标签,否则深层字段丢失
nil、缺失字段、类型不匹配时怎么处理
json.Unmarshal 默认“尽力而为”:不因单个字段失败而中断整个解析,但这也容易掩盖问题。
-
null写入指针字段 → 字段变nil(适合可选字段) -
null写入普通int字段 → 值不变(若未初始化就是0) - JSON 字段缺失 → 目标字段保持原值(不会被清空)
- 字符串塞进
int字段 → 跳过该字段,继续解析其余部分 - 想强制校验?得自己加逻辑,比如解析后检查
p.Name == ""并返回错误
什么时候该用 json.Decoder 而不是 Unmarshal
json.Unmarshal 要求整个 JSON 已加载到内存;json.Decoder 从 io.Reader 流式读取,适合大文件、HTTP 响应体或网络连接。
- 读文件:
file, _ := os.Open("data.json"); decoder := json.NewDecoder(file) - 读 HTTP body:
decoder := json.NewDecoder(resp.Body) - 注意:
Decode(&v)每次只解析一个 JSON 值;输入含多个对象需循环调用 - 流式解析无法回溯,错误发生时已读字节不可恢复
最常被忽略的点:解析后不检查关键字段是否仍为零值,就直接参与业务逻辑——尤其是时间、ID、金额这类字段,零值可能触发默认分支或静默错误。别只信 err == nil,要真看 p 本身。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










