用json.Marshal序列化结构体再os.WriteFile写入是最常用方式;字段须首字母大写导出,否则忽略;需加struct tag控制键名与omitempty;务必检查error并确保路径存在、权限正确。

用 json.Marshal 序列化结构体再写入文件最常用
Go 标准库没有直接“把结构体存成文件”的函数,得先序列化再写磁盘。最稳妥、跨语言兼容的方式是转成 JSON,用 json.Marshal 处理。注意结构体字段必须是导出的(首字母大写),否则 json.Marshal 会忽略它们。
常见错误是字段没导出,结果写出来是个空对象 {} 或部分字段丢失;还有忘记处理返回的 error,导致写入失败却无提示。
实操建议:
- 结构体字段加
jsontag 控制键名和可选性,比如Name string `json:"name"`或Age int `json:"age,omitempty"` - 用
os.WriteFile一步写入,比手动开文件、写、关更简洁且自动处理错误 - 如果数据量大或需流式写入,改用
json.NewEncoder(file).Encode(v),避免一次性加载全部 JSON 字符串到内存
用 gob 编码适合 Go 内部服务间传输
gob 是 Go 原生二进制格式,性能比 JSON 高、体积小,但只适用于 Go 程序之间读写——其他语言基本无法解析。如果你只是临时保存状态、测试数据或微服务内部缓存,gob 是更轻量的选择。
立即学习“go语言免费学习笔记(深入)”;
容易踩的坑:写之前没调用 gob.Register 注册自定义类型(尤其是含 interface 或 map[string]interface{} 的结构),会导致运行时报错 gob: type not registered for interface;还有写完没 Close(),文件内容可能不完整。
实操建议:
- 写前确保结构体类型已注册:
gob.Register(MyStruct{})(或传指针) - 用
gob.NewEncoder(f).Encode(v),别用Encode的变体如EncodeValue,除非你明确需要反射控制 - 写完立刻
f.Close(),或用defer f.Close(),否则Encode可能缓冲未刷盘
写文件时权限和路径错误常被忽略
用 os.WriteFile 或 os.Create 时,默认权限是 0600(仅当前用户可读写),如果后续要被其他程序读取,得显式指定 0644;路径里含不存在的父目录,会直接报错 no such file or directory,而不会自动创建。
实操建议:
- 写文件前用
os.MkdirAll(filepath.Dir(filename), 0755)确保目录存在 - 权限参数别硬写数字,用
0644而不是int(0644),Go 对八进制字面量有特殊语法支持 - 路径尽量用
filepath.Join("data", "user.json")拼接,避免手动拼"data/user.json"在 Windows 上出错
结构体含时间、通道、函数等字段会 panic
json.Marshal 和 gob.Encoder 都不支持直接序列化 time.Time(JSON 默认转成字符串,但需额外处理)、chan、func、unsafe.Pointer 等类型。碰到这些字段,要么忽略(加 json:"-" 或 gob:"-" ),要么实现自定义的 MarshalJSON 方法。
典型现象是运行时报 json: unsupported type: chan int 或 gob: type not supported。很多人卡在这里,以为是写法问题,其实是字段本身不可序列化。
实操建议:
- 含
time.Time的结构体,优先用jsontag 指定格式,如CreatedAt time.Time `json:"created_at" time_format:"2006-01-02T15:04:05Z"`(需配合自定义 marshaler) - 不要试图序列化
chan或func,它们属于运行时状态,不属于数据本身 - 如果结构体嵌套深、字段多,先用
fmt.Printf("%#v", v)看实际值类型,比猜更快定位不可序列化字段
os.WriteFile 报错后不检查 err,就等于静默丢数据。


















