Golang使用encoding/binary与gob读写二进制文件
本文解析了 Golang 中处理二进制数据的两种核心方式:针对自定义格式的 encoding/binary 包和针对复杂结构体的 encoding/gob 包。涵盖序列化写入、反序列化读取的代码实操,帮助开发者在不同场景下选择高效的数据持久化方案。
选择合适的二进制处理方式
Golang 标准库提供了多种序列化数据的手段。如果需要严格控制二进制文件的内容、长度以达到最紧凑的数据表示和更快的读写速度,应使用 encoding/binary 包。该包负责数字与字节序列之间的简单转换,支持 varints(变长整数)等编码方式。而若需要快速将 Go 的结构体(Struct)、切片等内置数据结构保存到文件或进行网络传输(如 RPC),encoding/gob 包则是更便捷的选择,其用法类似于 JSON 或 Protocol Buffers。
方法一:使用 encoding/binary 处理自定义格式
encoding/binary 允许开发者定义具体的数据布局。在进行二进制操作前,务必注意字节序(Endianness)。对于大多数跨平台通用的系统,小端模式(binary.LittleEndian)是常见的选择;若需与 Intel/AMD x86 体系或其他特定硬件交互,可相应调整为大端模式(binary.BigEndian)。
第1步:创建文件并准备缓冲区
首先打开或创建一个文件用于持久化存储。在处理单个数据块时,建议先写入内存中的 bytes.Buffer,确认无误后再批量写入磁盘,以减少 IO 次数。
第2步:执行序列化写入
使用 binary.Write 函数,配合目标缓冲区和字节序,将结构体转换为字节流:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
type User struct {
Age int32
}
func main() {
file, err := os.Create("bin")
if err != nil {
fmt.Println("文件创建失败 ", err.Error())
return
}
defer file.Close()
for i := 1; i <= 10; i++ {
data := User{
int32(i),
}
// 1. 准备缓冲
var buf bytes.Buffer
// 2. 序列化为字节
binary.Write(&buf, binary.LittleEndian, data)
b := buf.Bytes()
// 3. 写入文件
_, err = file.Write(b)
if err != nil {
fmt.Println("写入失败", err.Error())
return
}
}
fmt.Println("序列化成功")
}
第3步:执行反序列化读取
读取时需要预先知道每个字段的字节长度(例如 int32 占用 4 个字节)。读取指定长度的字节后,放入 Buffer 并调用 binary.Read:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
type User struct {
Age int32
}
func main() {
file, err := os.Open("bin")
if err != nil {
fmt.Println("文件打开失败 ", err.Error())
return
}
defer file.Close()
data := User{}
for i := 1; i <= 10; i++ {
// 1. 预分配对应字段大小的字节数组
b := make([]byte, 4)
_, err = file.Read(b)
if err != nil {
fmt.Println("反序列化失败", err)
}
// 2. 创建 Buffer
buffer := bytes.NewBuffer(b)
// 3. 读取并填充到结构体
err = binary.Read(buffer, binary.LittleEndian, &data)
if err != nil {
fmt.Println("二进制文件读取失败", err)
return
}
fmt.Println("第", i, "个值为:", data)
}
}
方法二:使用 encoding/gob 处理结构体对象
当数据较为复杂且不需要手动控制底层字节偏移量时,可以使用 encoding/gob。它自动记录结构体类型信息并进行编码/解码,非常适合本地缓存或内部通信。
第1步:初始化 Gob Encoder
使用 gob.NewEncoder(file) 获取编码器实例,然后直接调用 Encode 传入任意类型的变量:
package main
import (
"encoding/gob"
"fmt"
"os"
)
func main() {
data := "测试读写二进制文件"
file, err := os.Create("bin") // 创建文件
if err != nil {
fmt.Println("文件创建失败", err.Error())
return
}
defer file.Close()
encoder := gob.NewEncoder(file)
err = encoder.Encode(data)
if err != nil {
fmt.Println("编码错误", err.Error())
return
}
}
第2步:初始化 Gob Decoder 并读取
读取时反向操作,先定义好接收数据的变量,通过 decoder.Decode(&variable) 还原内容:
package main
import (
"encoding/gob"
"fmt"
"os"
)
func main() {
file, err := os.Open("bin")
if err != nil {
fmt.Println("文件打开失败", err.Error())
return
}
defer file.Close()
decoder := gob.NewDecoder(file)
var data string
err = decoder.Decode(&data)
if err != nil {
fmt.Println("解码失败", err.Error())
return
}
fmt.Println(data)
}
排错提示
- Read at end of file:在使用
encoding/binary逐条读取时,若未检查err == io.EOF可能会导致循环继续尝试读取空数据引发 panic 或错误输出,建议在读取前校验错误状态。 - 类型不匹配:
gob编解码必须保证两端的数据类型完全一致(包括大小写),且必须是导出类型(首字母大写)的 Struct 才能被正确序列化。
以上就是 Golang 读写二进制文件方法的详细内容,更多关于 Golang 数据序列化与持久化的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













