golang binary包快速入门

binary

它的作用用一句话说就是:实现数据与二进制之间的双向转换

它有许多使用场景,比如:

  • 读取(解析)网络过来的二进制数据
  • 读取一个二进制文件
  • 将一个数据写成二进制

大小端字节序

开始之前先大概说下,大小端字节序,简单理解就是字节的编码顺序,一个从高位开始,一个从低位开始。

我们使用时候主要需要保证读和写的顺序保持一致就行,如果需要详细了解可以看这篇

1. 单一数据转换

好啦!我们开始来看最简单的,将一个简单数据,比如一个字符、一个数值转换成二进制

对于一些单一的字符读写可以使用,binary提供的binary.BigEndianbinary.LittleEndian完成。

go 复制代码
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	var a uint64 = 56

	// 用于存二进制数据
	bData := make([]byte, 8) // 64位 8个字节
  // a 写入到bData中
	binary.LittleEndian.PutUint64(bData, a)

	// 从bData读取 数据到b中
	b := binary.LittleEndian.Uint64(bData)

	fmt.Println(b)
}

// 56

2. 复杂(结构体)数据转换

需要注意的是,binary包处理的数据必须要有固定的长度,所以对结构体的字段类型有要求。

go 复制代码
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

// 需要注意的是在binary 出来的数据必须要有固定的长度
type Data struct {
	ID         uint16
	Temprature float32
	Records    [4]byte // 4个长度字节数组
}

func main() {
	// 准备好要转换的数据
	datas := []Data{
		{ID: 12, Temprature: 21.8, Records: [4]byte{'A', 'B', 'C', 'D'}},
		{ID: 2, Temprature: 28.8, Records: [4]byte{'B', 'B', 'C', 'A'}},
	}

	// 具有io.Writer 和 io.Reader的 缓冲对象用于存二进制数据
	var buf = new(bytes.Buffer)
	// 将数据写入buf中 记住这里最后一个参数必须是引用(比如指针,这里切片本身就是引用所以无所谓)
	binary.Write(buf, binary.LittleEndian, datas)

	parseData := make([]Data, 2) // 存解析出来的数据
	// 从buf中读取 解析成Data结构体切片
	binary.Read(buf, binary.LittleEndian, parseData)

	fmt.Printf("%#v\n", parseData[0])
	fmt.Printf("%#v\n", parseData[1])
	fmt.Printf("ID: %d , Temprature: %v, Record1: %c\n", parseData[0].ID, parseData[0].Temprature, parseData[0].Records[0])
}

// main.Data{ID:0xc, Temprature:21.8, Records:[4]uint8{0x41, 0x42, 0x43, 0x44}}
// main.Data{ID:0x2, Temprature:28.8, Records:[4]uint8{0x42, 0x42, 0x43, 0x41}}
// ID: 12 , Temprature: 21.8, Record1: A

3. 写二进制数据到文件

go 复制代码
package main

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"os"
)

func main() {
	file, err := os.OpenFile("data.bin", os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Println("创建文件错误")
		return
	}

	defer file.Close()

	// 封装一层缓冲区
	buf := bufio.NewWriter(file)
	// 写入缓冲中
	binary.Write(buf, binary.LittleEndian, []byte("hello world\n")) // 第一次写入 12个字节
	binary.Write(buf, binary.LittleEndian, []byte("beautiful!\n"))  // 第二次写入11字节

	// 从缓冲写入文件
	buf.Flush()

	// 从 文件中读取
	f, err := os.Open("data.bin")
	if err != nil {
		fmt.Println("打开文件失败:", err.Error())
		return
	}

	// 构造一个读bufio
	reader := bufio.NewReader(f)
	// 第一次读取 12个字节
	a := make([]byte, 12)
	binary.Read(reader, binary.LittleEndian, a)
	fmt.Printf("%s", a)
	// 第二次读取11个字节
	binary.Read(reader, binary.LittleEndian, a[0:11])
	fmt.Printf("%s", a[0:11])
}

// hello world
// beautiful!

4. 总结

本质上binary包只有两个操作: 一个写,一个读;分别对应两种转换:

  1. 写 - (数据->二进制)
  2. 读 - (二进制 -> 数据)
相关推荐
研究司马懿9 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大1 天前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰1 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo