如何在Golang中处理二进制文件_Golang encoding/binary读写方法
技术百科
P粉602998670
发布时间:2026-01-23
浏览: 次 Go中binary.Write必须显式指定字节序(LittleEndian或BigEndian),否则panic;结构体需导出字段且用定长类型;变长字段须分步处理长度与内容;网络读取需确保io.ReadFull完整读取。
binary.Write 写入二进制数据时字节序必须显式指定
Go 的 encoding/binary 不提供默认字节序,binary.Write 第二个参数必须传入 binary.LittleEndian 或 binary.BigEndian。漏传会 panic:panic: binary.Write: invalid type interface {}(实际是因未传入 binary.ByteOrder 导致内部反射失败)。
常见写法:
data := uint32(0x12345678) err := binary.Write(w, binary.LittleEndian, data)
注意:w 必须是实现了 io.Writer 的类型(如 *os.File、bytes.Buffer)。结构体写入也同理,字段必须导出且按顺序连续编码。
读取固定长度结构体需确保内存布局与写入一致
用 binary.Read 读结构体时,Go 会按字段声明顺序逐个解码,但不会跳过填充字节。若结构体含 int、uintptr 等平台相关类型,或字段间有未导出字段,读写结果必然错乱。
安全做法是只使用定长基础类型,并显式对齐:
- 用
uint32代替int,用[32]byte代替string - 结构体加
// +build ignore注释无用,真正有效的是unsafe.Sizeof校验 - 读之前先确认文件/缓冲区剩余字节数 ≥ 结构体大小,否则
binary.Read返回io.ErrUnexpectedEOF
处理变长字段(如字符串、切片)不能直接用 binary.Read/Write
binary.Read 和 binary.Write 对 []byte、string 只写入长度(作为 uint64),不写内容;对 slice 类型甚至直接报错:binary.Read: invalid type 。
正确方式是分步处理:
str := "hello" // 先写长度 binary.Write(w, binary.LittleEndian, uint64(len(str))) // 再写字节流 w.Write([]byte(str))
读取时反向操作:先读 uint64 得长度 n,再用 io.ReadFull(r, make([]byte, n)) 读内容。忽略长度校验会导致越界或阻塞。
binary.Read 从网络连接读取时容易卡在 partial read
当 r 是 net.Conn 或其他非阻塞 reader 时,binary.Read(r, order, &v) 可能只读到部分字节就返回 nil 错误(实际是成功读了几个字节),导致后续解析错位。
根本原因是 binary.Read 底层调用 io.ReadFull,而 io.ReadFull 要求「必须读满」,否则返回 io.ErrUnexpectedEOF 或 io.EOF。但网络连接可能暂时没发完,需重试:
- 包装
r为bufio.Reader并设置足够大缓存 - 或手动循环调用
io.ReadFull直到成功,不依赖binary.Read自动重试 - 更稳妥的做法:用
io.ReadFull(r, buf)先读原始字节,再用binary.Read(bytes.NewReader(buf), ...)解析
字节序、结构体对齐、变长字段边界、IO 完整性——这四点漏掉任一个,二进制读写就会静默出错,且很难通过日志定位。
# 的是
# 就会
# 几个
# 很难
# 第二个
# 或其他
# 再用
# go
# golang
# 循环
# String
# int
# 编码
# 字节
# 字符串
# nil
# Interface
# 重试
# 结构体
# 切片
# 定长
# EOF
# 变长
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- php本地部署后session无法保存_sessi
- 如何在Golang中实现基础配置管理功能_Gola
- Win11怎么激活Windows10_Win11激
- 如何在 Go 中高效缓存与分发网络视频流
- Win11玩游戏全屏闪退怎么办_Win11全屏优化
- php和redis连接超时怎么办_phpredis
- Python函数缓存机制_lru_cache解析【
- 如何在Golang中捕获HTTP服务器错误_Gol
- Python变量绑定机制_引用模型解析【教程】
- Win11怎么关闭专注助手 Win11关闭免打扰模
- Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱
- c++中如何使用auto关键字_c++11类型推导
- Win11怎样安装钉钉客户端_Win11安装钉钉教
- c++输入输出流 c++ cin与cout格式化输
- php8.4如何调用com组件_php8.4win
- c++20的std::format怎么用 比pri
- Python音视频处理高级项目教程_FFmpegP
- Windows10如何删除Windows.old_
- Win11怎么查看显卡温度 Win11任务管理器查
- Windows怎样关闭Edge新标签页广告_Win
- 如何自定义Windows终端的默认配置文件?(Po
- Win11怎么查看wifi信号强度_检测Windo
- Win11如何关闭小娜Cortana Win11禁
- PHP主流架构如何做单元测试_工具与流程【详解】
- Win11怎么关闭触摸屏_禁用Win11笔记本触摸
- C++如何编写函数模板?(泛型编程入门)
- Mac如何开启夜览模式_Mac护眼模式设置与定时
- php命令行怎么运行_通过CLI模式执行PHP脚本
- Windows11如何设置专注助手_Windows
- 如何在JavaScript中动态拼接PHP的bas
- Python解释执行模型_字节码流程说明【指导】
- 如何在Golang中实现CI/CD流水线自动化测试
- 如何在Golang中实现邮件发送功能_Golang
- 本地php环境打开php文件直接下载_浏览器解析p
- php订单日志怎么按金额排序_php按订单金额排序
- Win11如何设置文件关联 Win11修改特定文件
- Win10电脑怎么设置网络名称_Windows10
- Win11怎么设置环境变量_Win11配置Path
- Windows 11怎么更改锁屏超时时间_Wind
- Python lxml的etree和Element
- Win11怎么关闭透明效果_Windows11个性
- php查询数据怎么导出csv_查询结果转csv文件
- Avalonia如何实现跨窗口通信 Avaloni
- Go 语言标准库为何不提供泛型 Contains
- php订单日志怎么记录发货_php记录订单发货操作
- php怎么下载安装后测试是否成功_简单脚本验证方法
- Win10系统字体模糊怎么办_Windows10高
- Win11怎么开启游戏模式_Windows11优化
- php删除数据怎么加限制_带where条件删除避免
- Win11怎么设置多显示器任务栏 Win11扩展任

QQ客服