最稳妥方式是先用 json.marshal 序列化结构体为字节切片,再用 os.writefile 写入文件;需确保字段导出、添加 json tag、严格检查每一步 error。

用 json.Marshal 序列化结构体再写入文件最稳妥
Go 标准库不提供直接“一键保存 JSON 到文件”的函数,必须分两步:先序列化为字节切片,再写入文件。跳过 json.Marshal 直接用 json.Encoder 虽可行,但出错时难定位是数据问题还是 IO 问题。
常见错误:结构体字段没加导出(首字母小写),导致序列化后是空对象 {};或忘记处理 json.Marshal 返回的 error,结果写入了 nil 字节流。
- 确保结构体字段首字母大写,且加上
jsontag(如Username string `json:"username"`) - 始终检查
json.Marshal的 error,不要忽略 - 写文件建议用
os.WriteFile(Go 1.16+),简洁且自动处理 close
data := struct{ Name string `json:"name"` }{Name: "Alice"}
b, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
err = os.WriteFile("user.json", b, 0644)
if err != nil {
log.Fatal(err)
}
用 json.Encoder 流式写入适合大数据或嵌套结构
当你要写入大量 JSON(比如数组元素逐个生成)、或结构体嵌套很深、或需控制缩进/换行时,json.Encoder 更灵活。它直接写入 io.Writer,可接文件、网络连接甚至内存 buffer。
容易踩的坑:忘记调用 encoder.Encode()(不是 EncodeAll),或误以为一次 Encode 能写多个值——它每次只写一个 JSON 值,多次调用会生成多个独立 JSON 对象(非合法 JSON 数组)。
立即学习“go语言免费学习笔记(深入)”;
Delphi 7应用编程150例 CHM全书内容下载,全书主要通过150个实例,全面、深入地介绍了用Delphi 7开发应用程序的常用方法和技巧,主要讲解了用Delphi 7进行界面效果处理、图像处理、图形与多媒体开发、系统功能控制、文件处理、网络与数据库开发,以及组件应用等内容。这些实例简单实用、典型性强、功能突出,很多实例使用的技术稍加扩展可以解决同类问题。使用本书最好的方法是通过学习掌握实例中的技术或技巧,然后使用这些技术尝试实现更复杂的功能并应用到更多方面。本书主要针对具有一定Delphi基础知识
- 写入数组需手动输出
[和],并在元素间加逗号 - 用
encoder.SetIndent("", " ")可美化输出(但有性能开销) - 如果写入失败,error 发生在
Encode()调用时,不是Close()时
f, _ := os.Create("users.json")
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
enc.Encode(map[string]string{"id": "1", "role": "admin"})
enc.Encode(map[string]string{"id": "2", "role": "user"})
// 注意:这会生成两行独立 JSON,不是 { ... } 包裹的数组
读取 JSON 文件务必检查 json.Unmarshal 的 error
很多人只检查 os.Open 错误,却忽略 json.Unmarshal 失败——比如文件内容是 {name: "bob"}(key 缺少引号),或类型不匹配(JSON 中是字符串,Go 结构体字段却是 int)。
典型现象:程序不报错,但结构体字段全是零值(""、0、nil),调试时才发现是 unmarshal 失败被静默吞掉了。
- 永远用
err != nil判断json.Unmarshal是否成功 - 若 JSON 字段可能缺失或类型不确定,用
map[string]interface{}或自定义UnmarshalJSON方法 - 避免用
json.RawMessage过度延迟解析,除非真需要跳过某段结构校验
注意文件权限与路径,Windows 和 Linux 行为一致但路径分隔符要小心
os.WriteFile 和 os.Open 在 Windows 和 Linux 下对路径分隔符都支持 /(Go 运行时自动转换),但硬编码 \ 会导致编译失败或路径错误。另外,文件权限参数(如 0644)在 Windows 上被忽略,但在 Linux/macOS 上决定能否读写。
- 路径拼接统一用
path/filepath.Join,别用字符串 + - 写入前确保目录存在,
os.WriteFile不会自动创建父目录,要用os.MkdirAll - 临时测试时避免写到根目录或系统路径,优先用相对路径如
./data/config.json
最常被忽略的是:JSON 写入后没刷新缓冲区(其实 os.WriteFile 和 json.Encoder 的 Close 都已处理),但如果你用 bufio.Writer 包装文件,就一定得记得 Flush() ——否则内容可能卡在内存里没落盘。









