
`json.unmarshal` 返回的是错误值(Error),而非解析结果;若返回 `nil` 表示解析成功,实际数据已写入目标变量,需通过变量本身访问解码后的内容。
在 go 中,encoding/json.Unmarshal 函数的签名是:
func Unmarshal(data []byte, v interface{}) error
它不返回解码后的值,而是将解析结果“填充”到传入的指针变量 v 中,并仅返回一个 error 类型的返回值:nil 表示成功,非 nil 表示解析失败(如格式错误、类型不匹配、字段不可导出等)。
你原代码中:
uncoded := json.Unmarshal(coded, &p) fmt.Println("Unmarshalled:", uncoded) // ❌ 打印的是 error,不是 p!
uncoded 是 error 类型,打印
✅ 正确用法如下:
coded := redis.LoadFromBase() err := json.Unmarshal(coded, &p) if err != nil { log.Fatalf("JSON 解析失败: %v", err) } fmt.Println("Bytes:", coded) fmt.Println("Unmarshalled:", p) // ✅ 此处打印解析后的结构体/值
? 关键注意事项:
- 确保 p 是可寻址的变量(即必须传 &p,不能传 p);
- 若 p 是结构体,其字段名须首字母大写(可导出),否则 json 包无法写入;
- 建议始终检查 err,即使日志中看到
也不代表可跳过错误处理——生产环境必须显式判断; - 可配合 json.Marshal(p) 回序列化验证是否还原一致,辅助调试。
示例完整验证片段:
type Post struct { Title string `json:"Title"` Content string `json:"Content"` } p := Post{} coded := []byte(`{"Title":"a","Content":"b"}`) err := json.Unmarshal(coded, &p) if err != nil { panic(err) } fmt.Printf("解析成功 → %+vn", p) // 输出:{Title:"a" Content:"b"}
记住:Unmarshal 是“写入式”操作,它的返回值只告诉你“有没有出错”,而不是“解出来什么”。理解这一点,就能避免绝大多数 JSON 解析的困惑。