gob解码必须传指针,否则字段全为空;正确写法为dec.decode(&u),错误写法为dec.decode(u),因decode需通过指针修改原变量,传值则无效果且静默失败。

gob序列化必须传指针,否则字段全为空
用 encoding/gob 序列化结构体时,如果反序列化目标变量不是指针,Decode() 会静默失败——字段值全为零,也不报错。这是最常踩的坑。
- 正确写法:
var u User; dec.Decode(&u)(传&u) - 错误写法:
dec.Decode(u)(传值,解码无效果) - 嵌套结构体、map、slice 同样要求接收变量为指针,否则内部字段不生效
- 若用
interface{}接收,必须提前调用gob.Register(&MyType{}),否则 panic 报gob: unknown type id
gob不跨语言,别在API或持久化场景硬上
gob 是 Go 内部协议,带类型元信息,Python/Java 完全无法解析。它只适合短期、可信、同版本 Go 进程间通信,比如本地缓存、RPC 内部传输。
- 对外暴露数据(如 HTTP API、数据库存档、日志文件)请用
encoding/json或protobuf - 字段增删改名后,老版本程序 decode 会 panic:
gob: field mismatch或type not found - 浮点数 NaN/+Inf/-Inf 在不同 Go 版本间行为可能不一致,不适合金融等精确场景
binary.Write 手写二进制格式更可控也更轻量
当协议固定、性能敏感(如高频网络包、嵌入式设备通信),直接用 encoding/binary 比 gob 更合适:无反射开销、无类型头、字节布局完全可控。
- 结构体字段必须是基本类型或固定长度数组(如
[16]byte),避免string或slice - 写入顺序必须和读取顺序严格一致;大小端要统一(常用
binary.BigEndian) - 建议加魔数校验(如开头写
[4]byte{0x47, 0x4F, 0x42, 0x01})和长度校验,防止错位解析 - 示例:时间字段存
int64秒级时间戳,比 JSON 的 RFC3339 字符串节省 15+ 字节且解析更快
json.Marshaler 和 BinaryMarshaler 不是替代方案,而是补充手段
标准序列化不够用时(比如字段需脱敏、加密、兼容旧协议),才需要实现 json.Marshaler 或 BinaryMarshaler。它们不是为了“替换”标准库,而是让某个字段或结构体自主控制编解码逻辑。
- 实现
MarshalJSON()时,避免调用json.Marshal(this),否则递归溢出 - 实现
UnmarshalJSON([]byte)时,先用json.RawMessage延迟解析,再按需提取字段,提升灵活性 - 二进制场景用
BinaryMarshaler,可结合sync.Pool复用bytes.Buffer,减少 GC 压力 - 所有自定义 marshaler 都需配套单元测试,尤其覆盖边界情况(空值、非法输入、截断字节)
gob 往往只用在服务内部状态快照或进程间 pipe 通信;真正落地的二进制协议,十有八九是手写 binary.Write + 魔数校验 + 版本号字段——控制权在自己手里,出问题能立刻定位到字节偏移。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











