用 json.Marshal 序列化 map 再写入文件最常用,需使用 map[string]interface{}(key 必须为字符串),配合 json.MarshalIndent 生成格式化 JSON,再用 os.WriteFile 写入,注意提前创建目录并检查错误。

用 json.Marshal 序列化 map 再写入文件最常用
Go 原生不支持直接把 map 二进制写进文件,必须先序列化。JSON 是最轻量、可读性强、跨语言兼容的首选方式,尤其适合配置、日志、调试数据等场景。
注意:key 必须是字符串(map[string]interface{} 或 map[string]T),否则 json.Marshal 会报错 json: unsupported type: map[interface {}]interface{}。
实操建议:
- 用
json.MarshalIndent生成带缩进的格式化 JSON,方便人工查看 - 写入前检查 error,
os.WriteFile比os.Open+Write更简洁安全 - 如果 map 值含自定义 struct,确保字段首字母大写(导出)且有 JSON tag(如
json:"name")
data := map[string]interface{}{
"host": "localhost",
"port": 8080,
"tags": []string{"api", "v1"},
}
b, err := json.MarshalIndent(data, "", " ")
if err != nil {
log.Fatal(err)
}
err = os.WriteFile("config.json", b, 0644)
if err != nil {
log.Fatal(err)
}
写入二进制文件要用 gob,但仅限 Go 内部使用
gob 是 Go 自带的二进制序列化机制,能完整保留 map 类型(包括 map[int]string 这类非字符串 key),但生成的文件只能被 Go 程序读取,不可读、不跨语言。
立即学习“go语言免费学习笔记(深入)”;
常见错误:没调用 enc.Encode() 或忘记 defer enc.Close() 导致数据未刷入磁盘;或用 gob.NewDecoder 读时类型不匹配 panic。
实操建议:
- 必须先注册所有可能用到的 map value 类型(如果含 interface{} 或自定义 struct),用
gob.Register() - 写入后立即关闭 encoder,否则部分数据可能丢失
- 文件扩展名建议用
.gob,避免误当文本打开
f, _ := os.Create("data.gob")
defer f.Close()
enc := gob.NewEncoder(f)
err := enc.Encode(map[int]string{1: "a", 2: "b"})
if err != nil {
log.Fatal(err)
}
map 数据量大时别直接 json.Marshal 到内存
如果 map 有几十万以上键值对,json.Marshal 会一次性分配大块内存,可能触发 GC 压力甚至 OOM。这时应流式写入。
正确做法是用 json.NewEncoder 直接写到文件句柄,边序列化边写磁盘,内存占用恒定。
实操建议:
- 不要用
bytes.Buffer中转,绕过内存峰值 - 注意
json.NewEncoder不支持直接写 map 的“顶层对象”,需包一层 struct 或用map[string]interface{} - 若需多对象追加(如日志行),每行一个 JSON 对象,用
encoder.Encode(item)多次调用即可
f, _ := os.Create("big.json")
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
err := enc.Encode(map[string]interface{}{"count": len(data), "items": data})
if err != nil {
log.Fatal(err)
}
文件路径和权限容易被忽略的细节
写文件失败常不是序列化问题,而是路径不存在或权限不足。Go 不会自动创建父目录,os.WriteFile 只写文件本身。
典型现象:open config.json: no such file or directory —— 实际是上层目录 ./output/ 不存在。
实操建议:
- 用
os.MkdirAll(filepath.Dir(path), 0755)提前创建完整路径 - 权限位别硬写
0644,Linux/macOS 下没问题,Windows 会忽略,但显式传参更可控 - 避免用相对路径写入(如
"./data/config.json"),优先用filepath.Join(os.Getenv("HOME"), "myapp", "data.json")明确落点
gob。别为了“看起来高级”而跳过路径创建和错误检查——它们才是真正在生产环境卡住你的地方。


















