binary.write要求结构体字段必须可导出(大写开头),不支持map/slice/string等动态类型,需手动处理内存对齐与字节序,否则读写会出错。

binary.Write 写入结构体前必须保证字段可导出
Go 的 binary.Write 无法序列化未导出(小写开头)字段,这是最常卡住的地方。它底层依赖 reflect,而反射看不到私有字段。
实操建议:
- 结构体所有要写入的字段名必须大写开头(如
Name而非name) - 如果字段是内嵌结构体,其内部字段也需全部可导出
- 不支持 map、slice、string 等动态长度类型直接写入——
binary.Write是固定布局二进制编码,只适合纯值类型组合 - 示例中若写
type User struct { name string },binary.Write不报错但实际不写入name字段,字节流里就少那段数据
struct 内存布局必须显式对齐,否则 binary.Read/Wrote 出错
Go 编译器会对结构体自动填充 padding,但不同平台、不同字段顺序可能导致填充位置不同。一旦你用 binary.Write 写出的数据,想在另一端(比如 C 程序或跨平台服务)读取,就必须控制内存布局。
实操建议:
- 用
//go:pack注释无效;正确方式是手动加byte字段占位,或用unsafe.Offsetof校验偏移 - 推荐使用
encoding/binary配合struct{}手动序列化:先写字段1,再写字段2……避开结构体整体写入 - 常见错误现象:
binary.Read: invalid type *T或读出的数值明显错乱(比如 int32 变成负数),大概率是字段对齐不一致 - 例如:
type Header struct { Ver uint8; Len uint32 }在 64 位系统上,Len实际偏移可能是 8 而非 5,因为编译器在Ver后补了 3 字节
endianness 必须和目标环境严格一致
binary.Write 第二个参数必须传入 binary.LittleEndian 或 binary.BigEndian,漏传或传错会导致整块数据翻转。这不是“能跑就行”的问题,而是字节序错一位,整个数值全错。
实操建议:
- 不要硬编码
binary.LittleEndian就完事——确认对方系统/协议要求的是哪种序。网络协议一般用大端,x86 程序本地存档常用小端 - 用
binary.Size(&v)检查结构体大小是否符合预期,能提前发现因字节序+对齐导致的 size 偏差 - 如果结构体含多个整数字段,建议逐字段调用
binary.Write,而不是传整个 struct 地址,这样更可控 - 错误示例:
binary.Write(w, binary.LittleEndian, &u)写入后,用 Pythonstruct.unpack(">i", data)(大端)去读,结果永远对不上
替代方案:什么时候不该用 binary.Write
如果你的结构体含 slice、map、string、interface{} 或指针,binary.Write 直接 panic:binary.Write: invalid type []int。它根本不是通用序列化工具。
实操建议:
- 需要存字符串?先写长度(uint32),再写 []byte(data)
- 需要存 slice?同理:先写 len,再循环写每个元素(前提是元素类型支持 binary)
- 更稳妥的选择:用
gob(Go 内置,支持复杂类型但仅限 Go 间通信),或protobuf(跨语言、强 schema),或手写MarshalBinary() ([]byte, error)方法 - 容易被忽略的一点:
binary.Write底层调用w.Write(),如果写入的是bytes.Buffer没问题;但如果是网络连接或文件,要注意错误返回并检查n, err := w.Write(...)是否写满
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











