基本介绍

GoFrame 框架提供了独立的二进制数据操作包 gbinary,主要用于各种数据类型与 []byte 二进制类型之间的相互转换;以及针对于整型数据进行精准按位处理的功能。常用于网络通信时数据编码/解码,以及数据文件操作时的编码/解码。

使用方式

  1. import "github.com/gogf/gf/v2/encoding/gbinary"

接口文档

https://pkg.go.dev/github.com/gogf/gf/v2/encoding/gbinary

用于二进制数据结构转换处理的接口文档如下:

  1. func Encode(vs ...interface{}) ([]byte, error)
  2. func EncodeInt(i int) []byte
  3. func EncodeInt8(i int8) []byte
  4. func EncodeInt16(i int16) []byte
  5. func EncodeInt32(i int32) []byte
  6. func EncodeInt64(i int64) []byte
  7. func EncodeUint(i uint) []byte
  8. func EncodeUint8(i uint8) []byte
  9. func EncodeUint16(i uint16) []byte
  10. func EncodeUint32(i uint32) []byte
  11. func EncodeUint64(i uint64) []byte
  12. func EncodeBool(b bool) []byte
  13. func EncodeFloat32(f float32) []byte
  14. func EncodeFloat64(f float64) []byte
  15. func EncodeString(s string) []byte
  16. func Decode(b []byte, vs ...interface{}) error
  17. func DecodeToInt(b []byte) int
  18. func DecodeToInt8(b []byte) int8
  19. func DecodeToInt16(b []byte) int16
  20. func DecodeToInt32(b []byte) int32
  21. func DecodeToInt64(b []byte) int64
  22. func DecodeToUint(b []byte) uint
  23. func DecodeToUint8(b []byte) uint8
  24. func DecodeToUint16(b []byte) uint16
  25. func DecodeToUint32(b []byte) uint32
  26. func DecodeToUint64(b []byte) uint64
  27. func DecodeToBool(b []byte) bool
  28. func DecodeToFloat32(b []byte) float32
  29. func DecodeToFloat64(b []byte) float64
  30. func DecodeToString(b []byte) string

支持按位处理的接口文档如下:

  1. func EncodeBits(bits []Bit, i int, l int) []Bit
  2. func EncodeBitsWithUint(bits []Bit, ui uint, l int) []Bit
  3. func EncodeBitsToBytes(bits []Bit) []byte
  4. func DecodeBits(bits []Bit) uint
  5. func DecodeBitsToUint(bits []Bit) uint
  6. func DecodeBytesToBits(bs []byte) []Bit

其中的Bit类型表示一个二进制数字(0或1),其定义如下:

  1. type Bit int8

使用示例

我们来看一个比较完整的二进制操作示例,基本演示了绝大部分的二进制转换操作。

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/encoding/gbinary"
  5. "github.com/gogf/gf/v2/os/gctx"
  6. "github.com/gogf/gf/v2/os/glog"
  7. )
  8. func main() {
  9. // 使用gbinary.Encoded对基本数据类型进行二进制打包
  10. if buffer := gbinary.Encode(18, 300, 1.01); buffer != nil {
  11. // glog.Error(err)
  12. } else {
  13. fmt.Println(buffer)
  14. }
  15. // 使用gbinary.Decode对整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,字长确定的类型,
  16. // 例如:int8/16/32/64、uint8/16/32/64、float32/64
  17. // 这里的1.01默认为float64类型(64位系统下)
  18. if buffer := gbinary.Encode(18, 300, 1.01); buffer != nil {
  19. //glog.Error(err)
  20. } else {
  21. var i1 int8
  22. var i2 int16
  23. var f3 float64
  24. if err := gbinary.Decode(buffer, &i1, &i2, &f3); err != nil {
  25. glog.Error(gctx.New(), err)
  26. } else {
  27. fmt.Println(i1, i2, f3)
  28. }
  29. }
  30. // 编码/解析 int,自动识别变量长度
  31. fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(1)))
  32. fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(300)))
  33. fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(70000)))
  34. fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(2000000000)))
  35. fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(500000000000)))
  36. // 编码/解析 uint,自动识别变量长度
  37. fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(1)))
  38. fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(300)))
  39. fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(70000)))
  40. fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(2000000000)))
  41. fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(500000000000)))
  42. // 编码/解析 int8/16/32/64
  43. fmt.Println(gbinary.DecodeToInt8(gbinary.EncodeInt8(int8(100))))
  44. fmt.Println(gbinary.DecodeToInt16(gbinary.EncodeInt16(int16(100))))
  45. fmt.Println(gbinary.DecodeToInt32(gbinary.EncodeInt32(int32(100))))
  46. fmt.Println(gbinary.DecodeToInt64(gbinary.EncodeInt64(int64(100))))
  47. // 编码/解析 uint8/16/32/64
  48. fmt.Println(gbinary.DecodeToUint8(gbinary.EncodeUint8(uint8(100))))
  49. fmt.Println(gbinary.DecodeToUint16(gbinary.EncodeUint16(uint16(100))))
  50. fmt.Println(gbinary.DecodeToUint32(gbinary.EncodeUint32(uint32(100))))
  51. fmt.Println(gbinary.DecodeToUint64(gbinary.EncodeUint64(uint64(100))))
  52. // 编码/解析 string
  53. fmt.Println(gbinary.DecodeToString(gbinary.EncodeString("I'm string!")))
  54. }

以上程序执行结果为:

  1. [18 44 1 41 92 143 194 245 40 240 63]
  2. 18 300 1.01
  3. 1
  4. 300
  5. 70000
  6. 2000000000
  7. 500000000000
  8. 1
  9. 300
  10. 70000
  11. 2000000000
  12. 500000000000
  13. 100
  14. 100
  15. 100
  16. 100
  17. 100
  18. 100
  19. 100
  20. 100
  21. I'm string!
  1. 编码

gbinary.Encode 方法是一个非常强大灵活的方法,可以将所有的基本类型转换为二进制类型 ([ ]byte)。在 gbinary.Encode 方法内部,会自动对变量进行长度计算,采用最小二进制长度来存放该变量的二进制值。例如,针对 int 类型值为 1 的变量, gbinary.Encode 将只会用 1byte 来存储,而 int 类型值为 300 的变量,将会使用 2byte 来存储,尽量减少二进制结果的存储空间。因此,在解析的时候要非常注意 [ ]byte 的长度,建议能够确定变量长度的地方,在进行二进制编码/解码时,尽量采用形如 int8/16/32/64 的定长基本类型来存储变量,这样解析的时候也能够采用对应的变量形式进行解析,不易产生错误。

gbinary 包也提供了一系列 gbinary.Encode* 的方法,用于将基本数据类型转换为二进制。其中, gbinary.EncodeInt/gbinary.EncodeUint 也是会在内部自动识别变量值大小,返回不定长度的 [ ]byte 值,长度范围 1/2/4/8

  1. 解码

在二进制类型的解析操作中,二进制的长度( [ ]byte 的长度)是非常重要的,只有给定正确的长度才能执行正确的解析,因此 gbinary.Decode 方法给定的变量长度必须为确定长度类型的变量,例如: int8/16/32/64uint8/16/32/64float32/64,而如果给定的第二个变量地址对应的变量类型为 int/uint,无法确定长度,因此解析会失败。

此外, gbinary 包也提供了一系列 gbinary.DecodeTo* 的方法,用于将二进制转换为特定的数据类型。其中, gbinary.DecodeToInt/gbinary.DecodeToUint 方法会对二进制长度进行自动识别解析,支持的二进制参数长度范围 1-8