golang自定义二进制流打包与解包插件库binpacker的使用

Golang自定义二进制流打包与解包插件库binpacker的使用

安装

go get github.com/zhuangsirui/binpacker

示例

打包器(Packer)使用

// 创建缓冲区
buffer := new(bytes.Buffer)
// 创建打包器,使用大端序
packer := binpacker.NewPacker(binary.BigEndian, buffer)
// 写入一个字节
packer.PushByte(0x01)
// 写入字节数组
packer.PushBytes([]byte{0x02, 0x03})
// 写入一个uint16
packer.PushUint16(math.MaxUint16)

也可以使用链式调用:

// 链式调用方式
buffer := new(bytes.Buffer)
packer := binpacker.NewPacker(binary.BigEndian, buffer)
packer.PushByte(0x01).PushBytes([]byte{0x02, 0x03}).PushUint16(math.MaxUint16)
// 检查是否有错误
packer.Error() // 确保错误为nil

解包器(Unpacker)使用

示例数据准备

buffer := new(bytes.Buffer)
packer := binpacker.NewPacker(binary.BigEndian, buffer)
unpacker := binpacker.NewUnpacker(binary.BigEndian, buffer)
// 写入测试数据
packer.PushByte(0x01)
packer.PushUint16(math.MaxUint16)

解包方式1

var val1 byte
var val2 uint16
var err error
// 读取一个字节
val1, err = unpacker.ShiftByte()
// 读取一个uint16
val2, err = unpacker.ShiftUint16()

解包方式2

var val1 byte
var val2 uint16
var err error
// 链式读取
unpacker.FetchByte(&val1).FetchUint16(&val2)
// 检查是否有错误
unpacker.Error() // 确保错误为nil

binpacker库提供了简单易用的二进制数据打包和解包功能,支持多种数据类型,并允许链式调用。使用时需要注意检查错误以确保操作成功。


更多关于golang自定义二进制流打包与解包插件库binpacker的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang自定义二进制流打包与解包插件库binpacker的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang二进制流打包与解包:binpacker库使用指南

binpacker是一个轻量级的Golang库,用于方便地进行二进制数据的打包与解包操作。它提供了简单的API来处理各种基本数据类型的二进制序列化。

安装

go get github.com/zhuangsirui/binpacker

基本用法

1. 打包数据

package main

import (
	"bytes"
	"fmt"
	"github.com/zhuangsirui/binpacker"
)

func main() {
	buffer := new(bytes.Buffer)
	packer := binpacker.NewPacker(buffer)

	// 打包不同类型的数据
	err := packer.PushUint16(12345)   // 2字节
	err = packer.PushString("hello")  // 字符串
	err = packer.PushFloat32(3.14)    // 4字节浮点数
	err = packer.PushBool(true)       // 1字节布尔值

	if err != nil {
		fmt.Println("打包出错:", err)
		return
	}

	// 获取打包后的二进制数据
	binData := buffer.Bytes()
	fmt.Printf("打包后的数据: %x\n", binData)
}

2. 解包数据

package main

import (
	"bytes"
	"fmt"
	"github.com/zhuangsirui/binpacker"
)

func main() {
	// 假设这是接收到的二进制数据
	binData := []byte{0x30, 0x39, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0xc3, 0xf5, 0x48, 0x40, 0x01}

	buffer := bytes.NewBuffer(binData)
	unpacker := binpacker.NewUnpacker(buffer)

	// 按打包顺序解包
	var num uint16
	var str string
	var pi float32
	var flag bool

	err := unpacker.ShiftUint16(&num)
	err = unpacker.ShiftString(&str)
	err = unpacker.ShiftFloat32(&pi)
	err = unpacker.ShiftBool(&flag)

	if err != nil {
		fmt.Println("解包出错:", err)
		return
	}

	fmt.Printf("解包结果: %d, %s, %f, %t\n", num, str, pi, flag)
}

支持的数据类型

binpacker支持以下数据类型的打包与解包:

  • 整数:PushInt8/16/32/64, ShiftInt8/16/32/64
  • 无符号整数:PushUint8/16/32/64, ShiftUint8/16/32/64
  • 浮点数:PushFloat32/64, ShiftFloat32/64
  • 布尔值:PushBool, ShiftBool
  • 字符串:PushString, ShiftString
  • 字节切片:PushBytes, ShiftBytes

高级用法

1. 处理结构体

type Person struct {
	ID     uint32
	Name   string
	Age    uint8
	Height float32
}

func PackPerson(p *Person) ([]byte, error) {
	buffer := new(bytes.Buffer)
	packer := binpacker.NewPacker(buffer)
	
	err := packer.PushUint32(p.ID)
	err = packer.PushString(p.Name)
	err = packer.PushUint8(p.Age)
	err = packer.PushFloat32(p.Height)
	
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}

func UnpackPerson(data []byte) (*Person, error) {
	buffer := bytes.NewBuffer(data)
	unpacker := binpacker.NewUnpacker(buffer)
	
	var p Person
	err := unpacker.ShiftUint32(&p.ID)
	err = unpacker.ShiftString(&p.Name)
	err = unpacker.ShiftUint8(&p.Age)
	err = unpacker.ShiftFloat32(&p.Height)
	
	if err != nil {
		return nil, err
	}
	return &p, nil
}

2. 处理变长数据

// 打包变长数据切片
func PackSlice(items []string) ([]byte, error) {
	buffer := new(bytes.Buffer)
	packer := binpacker.NewPacker(buffer)
	
	// 先写入长度
	err := packer.PushUint32(uint32(len(items)))
	if err != nil {
		return nil, err
	}
	
	// 再逐个写入元素
	for _, item := range items {
		err = packer.PushString(item)
		if err != nil {
			return nil, err
		}
	}
	
	return buffer.Bytes(), nil
}

// 解包变长数据切片
func UnpackSlice(data []byte) ([]string, error) {
	buffer := bytes.NewBuffer(data)
	unpacker := binpacker.NewUnpacker(buffer)
	
	var length uint32
	err := unpacker.ShiftUint32(&length)
	if err != nil {
		return nil, err
	}
	
	items := make([]string, length)
	for i := 0; i < int(length); i++ {
		err = unpacker.ShiftString(&items[i])
		if err != nil {
			return nil, err
		}
	}
	
	return items, nil
}

注意事项

  1. 字节序:binpacker默认使用大端序(BigEndian),如果需要小端序,需要自行处理
  2. 错误处理:每次打包/解包操作都可能返回错误,应该检查这些错误
  3. 数据对齐:确保打包和解包的顺序完全一致
  4. 性能考虑:对于高性能场景,可以考虑预分配足够大的buffer

binpacker是一个简单易用的二进制数据序列化库,适合协议编解码、文件格式处理等场景。对于更复杂的需求,也可以考虑protobuf、msgpack等更专业的序列化方案。

回到顶部