Golang使用encoding/binary与gob读写二进制文件

程一诺
程一诺
发布时间:2026-10-15| 5人浏览过
原创

本文解析了 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 数据序列化与持久化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。