使用方式

    接口文档

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

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

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

    2. 解码

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

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

    按位操作处理示例

    gbinaryBits相关操作简化了底层二进制位操作的复杂度,为精准的数据按位处理提供了可能。

    1. 批量传感器状态数据上报示例

      看以下的例子,用以上报平台100个传感器已开启,上报的状态顺序便是传感器在网关下端口顺序(索引从0开始):

      ``` package main

    1. gkvdb数据库META数据结构操作示例

      我们再看看一个实战的例子。gkvdbgf框架相同作者开发的基于DRH算法的高性能Key-Value嵌入式数据库,其中元数据的存储数据结构如下:

      1. [键名哈希64(64bit,8byte) 键名长度(8bit,1byte) 键值长度(24bit,3byte) 数据文件偏移量(40bit,5byte)](变长)

      我们使用一条元数据来演示编码/解码操作。

      github.com/gogf/gf/v2/blob/master/.example/encoding/gbinary/bits2.go

      ``` package main

    1. import (
    2. "fmt"
    3. "github.com/gogf/gf/v2/encoding/gbinary"
    4. )
    5. func main() {
    6. // Meta元数据文件数据结构:[键名哈希64(64bit,8byte) 键名长度(8bit,1byte) 键值长度(24bit,3byte) 数据文件偏移量(40bit,5byte)](变长)
    7. hash := 521369841259754125
    8. klen := 12
    9. vlen := 35535
    10. offset := 80000000
    11. // 编码
    12. bits := make([]gbinary.Bit, 0)
    13. bits = gbinary.EncodeBits(bits, hash, 64)
    14. bits = gbinary.EncodeBits(bits, klen, 8)
    15. bits = gbinary.EncodeBits(bits, vlen, 24)
    16. bits = gbinary.EncodeBits(bits, offset, 40)
    17. buffer := gbinary.EncodeBitsToBytes(bits)
    18. fmt.Println("meta length:", len(buffer))
    19. /* 文件存储及数据查询过程忽略,这里只展示元数据编码/解码示例 */
    20. // 解码
    21. metabits := gbinary.DecodeBytesToBits(buffer)
    22. fmt.Println("hash :", gbinary.DecodeBits(metabits[0 : 64]))
    23. fmt.Println("klen :", gbinary.DecodeBits(metabits[64 : 72]))
    24. fmt.Println("vlen :", gbinary.DecodeBits(metabits[72 : 96]))
    25. fmt.Println("offset:", gbinary.DecodeBits(metabits[96 : 136]))
    26. }
    27. ```
    28. 运行后,输出结果为:
    29. ```
    30. meta length: 17
    31. hash : 521369841259754125
    32. klen : 12
    33. vlen : 35535
    34. offset: 80000000
    35. ```