Go 中 JSON 反序列化失败的常见原因及正确用法

go 的 `json.unmarshal` 要求传入指向目标变量的指针,否则会因接收非指针值而静默失败(实际返回错误但被忽略),导致反序列化无效果。

在 Go 中,encoding/json.Unmarshal 函数的设计原则是:必须传入目标变量的地址(即指针),以便函数能直接修改该变量的内存内容。若传入非指针值(如 unmarshalled 本身),Unmarshal 会立即返回错误 json: Unmarshal(non-pointer map[string]string),但因代码中使用了 _ = json.Unmarshal(...) 忽略了错误,程序看似“运行成功”,实则 unmarshalled 仍为零值(空 map)。

以下是修复后的完整示例:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    m := map[string]string{"name": "Test"}
    j, err := json.Marshal(m)
    if err != nil {
        panic(err) // 或合理处理错误
    }
    fmt.Println("JSON:", string(j)) // 输出: {"name":"Test"}

    var unmarshalled map[string]string
    err = json.Unmarshal(j, &unmarshalled) // ✅ 关键:传入 &unmarshalled
    if err != nil {
        panic(err)
    }
    fmt.Printf("Unmarshalled: %+v\n", unmarshalled) // 输出: map[name:Test]
}

⚠️ 注意事项:

  • 永远检查 Unmarshal 的返回错误:忽略错误是调试 JSON 问题的最大陷阱;
  • 切片、结构体、map 等复合类型都需传指针(如 &mySlice, &myStruct, &myMap);
  • 若目标变量为 nil 指针(如 var p *map[string]string),Unmarshal 会自动分配新值;但此处 unmarshalled 是已声明的变量,只需取其地址即可;
  • 对于结构体字段,确保字段名首字母大写(导出)且有对应 JSON tag(如 json:"name"),否则无法反序列化。

总结:Go 的 JSON 反序列化不是“赋值操作”,而是“内存填充操作”,因此指针是必需的契约。养成 err != nil 检查习惯,并始终传递变量地址,可避免 90% 以上的反序列化失效问题。