
`json.unmarshal()`返回`nil`表示解析成功,而非失败;开发者常误将其当作解码后的值打印,实则它仅返回错误类型(error),解码结果存于传入的指针变量中。
在 Go 语言中,json.Unmarshal() 的函数签名是:
func Unmarshal(data []byte, v interface{}) error它不返回解码后的值,而是将解析结果写入第二个参数所指向的变量(必须传地址),并仅返回一个 error 类型的值:nil 表示解析成功,非 nil 表示 JSON 格式错误、字段不匹配、类型不兼容等异常。
你原始代码的问题在于:
uncoded := json.Unmarshal(coded, &p)
fmt.Println("Unmarshalled:", uncoded) // ❌ 错误:打印的是 error,不是 p!此处 uncoded 是 error 类型变量,输出
立即学习“go语言免费学习笔记(深入)”;
✅ 正确做法如下:
coded := redis.LoadFromBase()
err := json.Unmarshal(coded, &p)
if err != nil {
log.Fatalf("JSON unmarshal failed: %v", err)
}
// ✅ 此时 p 已被正确填充
fmt.Println("Bytes:", coded)
fmt.Println("Unmarshalled:", p) // ? 打印解码后的结构体/变量? 关键注意事项:
- &p 中的 p 必须是可寻址的变量(如局部变量、字段),且其类型需与 JSON 数据结构兼容(例如 JSON 对象对应 struct,需字段名匹配且导出);
- 若 p 是 nil 指针(如 var p *MyStruct 未初始化),json.Unmarshal 会尝试分配内存(仅对 nil 指针、nil slice、nil map 有效),但更推荐显式初始化以提升可读性;
- 建议始终检查 err:即使测试数据看似正常,生产环境中网络传输、存储损坏或格式变更都可能导致静默失败;
- 可配合 json.RawMessage 或 map[string]interface{} 进行动态解析,但强类型 struct + 字段标签(如 json:"title,omitempty")仍是推荐实践。
总结:json.Unmarshal 的设计遵循 Go 的“显式错误处理”哲学——成功无返回值(只返回 nil error),所有数据通过参数指针写回。牢记这一点,就能避免绝大多数“为什么解码后是空”的困惑。










