最简写法是json.marshal转字节切片后用os.writefile一次性写入,需确保结构体字段首字母大写或带json tag,目录存在,且分别检查marshal和writefile错误。

用 json.Marshal + os.WriteFile 最简写法
Go 标准库没有“一键 JSON 写文件”函数,但组合两步就能安全完成:先序列化,再写入。最轻量、最常用的方式就是 json.Marshal 转字节切片,再用 os.WriteFile 一次性写入。
注意:这适合中小数据量(比如配置、日志快照),不适用于流式大文件或需追加写入的场景。
示例:
data := map[string]interface{}{"name": "Alice", "age": 30}
b, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
err = os.WriteFile("user.json", b, 0644)
if err != nil {
log.Fatal(err)
}
-
os.WriteFile会自动创建文件、覆盖旧内容,不存在目录时会报错(需提前os.MkdirAll) - 权限
0644是 Unix 风格,Windows 上仅作占位,实际权限由系统策略决定 - 如果想格式化输出(带缩进),把
json.Marshal换成json.MarshalIndent(data, "", " ")
写入失败常见错误:空指针、未导出字段、循环引用
JSON 序列化失败不是写文件环节报错,而是 json.Marshal 阶段就 panic 或返回 error。最容易被忽略的是结构体字段没加导出标签。
示例错误代码:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
type User struct {
name string // 小写 → 不导出 → Marshal 后是空对象 {}
Age int // 大写 → 导出 → 正常序列化
}
- 结构体字段必须首字母大写,或显式加
json:"field_name"标签 - 含
nil指针字段(如*string)会写成null,但如果指针本身为nil且没设omitempty,仍会输出键值对 -
json.Marshal遇到 map 或 struct 包含自身引用(比如树节点含父指针)会直接 panic:json: unsupported value: encountered a cycle
需要追加写入或控制缓冲时,用 json.Encoder + os.File
当你要多次写入多个 JSON 对象(比如日志行、流式导出),或者担心内存占用(Marshal 全部加载到内存),就得绕过 os.WriteFile,改用带缓冲的 json.Encoder。
关键点:它写的是流,不是单个完整 JSON 文档;多个对象会连写,不自动换行、不加逗号分隔——这点和 NDJSON(JSON Lines)不同,得自己处理。
- 先
f, _ := os.OpenFile("log.json", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) - 再
enc := json.NewEncoder(f),然后反复调用enc.Encode(v) - 每次
Encode自动换行,但多个对象之间无分隔符,解析时需按行读取(json.Decoder支持逐行解码) - 记得
defer f.Close(),否则文件句柄泄漏,后续写入可能静默失败
中文乱码?别漏掉 json.Encoder.SetEscapeHTML(false)
默认情况下,json.Encoder 会把中文转成 \uXXXX 形式(为防 HTML 注入),导致文件里看不到可读汉字。这不是 bug,是设计行为。
解决方法很简单,在创建 encoder 后立刻设置:
enc := json.NewEncoder(f) enc.SetEscapeHTML(false) // 关键这一行
-
json.Marshal默认不转义中文,所以用os.WriteFile方式不会乱码 - 只有
json.Encoder默认开启 HTML 转义,且无法通过参数关闭,必须显式调用SetEscapeHTML(false) - 这个设置只影响字符串内容,不影响 JSON 结构本身
大文件、多层嵌套、带时间或二进制字段的场景,建议先小样测试 Marshal 输出是否符合预期,再决定用哪条路径。写文件本身很稳,出问题九成在序列化那步。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










