新聞中心
?GOframe?框架提供了獨(dú)立的二進(jìn)制數(shù)據(jù)操作包?gbinary?,主要用于各種數(shù)據(jù)類型與?[ ]byte?二進(jìn)制類型之間的相互轉(zhuǎn)換;以及針對(duì)于整型數(shù)據(jù)進(jìn)行精準(zhǔn)按位處理的功能。常用于網(wǎng)絡(luò)通信時(shí)數(shù)據(jù)編碼/解碼,以及數(shù)據(jù)文件操作時(shí)的編碼/解碼。

成都創(chuàng)新互聯(lián)是網(wǎng)站建設(shè)技術(shù)企業(yè),為成都企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站制作,網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制適合企業(yè)的網(wǎng)站。十年品質(zhì),值得信賴!
使用方式:
import "github.com/gogf/gf/v2/encoding/gbinary"接口文檔:
https://pkg.go.dev/github.com/gogf/gf/v2/encoding/gbinary
用于二進(jìn)制數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換處理的接口文檔如下:
func Encode(vs ...interface{}) ([]byte, error)
func EncodeInt(i int) []byte
func EncodeInt8(i int8) []byte
func EncodeInt16(i int16) []byte
func EncodeInt32(i int32) []byte
func EncodeInt64(i int64) []byte
func EncodeUint(i uint) []byte
func EncodeUint8(i uint8) []byte
func EncodeUint16(i uint16) []byte
func EncodeUint32(i uint32) []byte
func EncodeUint64(i uint64) []byte
func EncodeBool(b bool) []byte
func EncodeFloat32(f float32) []byte
func EncodeFloat64(f float64) []byte
func EncodeString(s string) []byte
func Decode(b []byte, vs ...interface{}) error
func DecodeToInt(b []byte) int
func DecodeToInt8(b []byte) int8
func DecodeToInt16(b []byte) int16
func DecodeToInt32(b []byte) int32
func DecodeToInt64(b []byte) int64
func DecodeToUint(b []byte) uint
func DecodeToUint8(b []byte) uint8
func DecodeToUint16(b []byte) uint16
func DecodeToUint32(b []byte) uint32
func DecodeToUint64(b []byte) uint64
func DecodeToBool(b []byte) bool
func DecodeToFloat32(b []byte) float32
func DecodeToFloat64(b []byte) float64
func DecodeToString(b []byte) string支持按位處理的接口文檔如下:
func EncodeBits(bits []Bit, i int, l int) []Bit
func EncodeBitsWithUint(bits []Bit, ui uint, l int) []Bit
func EncodeBitsToBytes(bits []Bit) []byte
func DecodeBits(bits []Bit) uint
func DecodeBitsToUint(bits []Bit) uint
func DecodeBytesToBits(bs []byte) []Bit其中的?Bit?類型表示一個(gè)二進(jìn)制數(shù)字(0或1),其定義如下:
type Bit int8
二進(jìn)制操作示例
我們來看一個(gè)比較完整的二進(jìn)制操作示例,基本演示了絕大部分的二進(jìn)制轉(zhuǎn)換操作。
github.com/gogf/gf/v2/blob/master/.example/encoding/gbinary/binary.go
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/encoding/gbinary"
)
func main() {
// 使用gbinary.Encoded對(duì)基本數(shù)據(jù)類型進(jìn)行二進(jìn)制打包
if buffer := gbinary.Encode(18, 300, 1.01); buffer != nil {
// glog.Error(err)
} else {
fmt.Println(buffer)
}
// 使用gbinary.Decode對(duì)整形二進(jìn)制解包,注意第二個(gè)及其后參數(shù)為字長確定的整形變量的指針地址,字長確定的類型,
// 例如:int8/16/32/64、uint8/16/32/64、float32/64
// 這里的1.01默認(rèn)為float64類型(64位系統(tǒng)下)
if buffer := gbinary.Encode(18, 300, 1.01); buffer != nil {
//glog.Error(err)
} else {
var i1 int8
var i2 int16
var f3 float64
if err := gbinary.Decode(buffer, &i1, &i2, &f3); err != nil {
glog.Error(err)
} else {
fmt.Println(i1, i2, f3)
}
}
// 編碼/解析 int,自動(dòng)識(shí)別變量長度
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(1)))
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(300)))
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(70000)))
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(2000000000)))
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(500000000000)))
// 編碼/解析 uint,自動(dòng)識(shí)別變量長度
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(1)))
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(300)))
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(70000)))
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(2000000000)))
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(500000000000)))
// 編碼/解析 int8/16/32/64
fmt.Println(gbinary.DecodeToInt8(gbinary.EncodeInt8(int8(100))))
fmt.Println(gbinary.DecodeToInt16(gbinary.EncodeInt16(int16(100))))
fmt.Println(gbinary.DecodeToInt32(gbinary.EncodeInt32(int32(100))))
fmt.Println(gbinary.DecodeToInt64(gbinary.EncodeInt64(int64(100))))
// 編碼/解析 uint8/16/32/64
fmt.Println(gbinary.DecodeToUint8(gbinary.EncodeUint8(uint8(100))))
fmt.Println(gbinary.DecodeToUint16(gbinary.EncodeUint16(uint16(100))))
fmt.Println(gbinary.DecodeToUint32(gbinary.EncodeUint32(uint32(100))))
fmt.Println(gbinary.DecodeToUint64(gbinary.EncodeUint64(uint64(100))))
// 編碼/解析 string
fmt.Println(gbinary.DecodeToString(gbinary.EncodeString("I'm string!")))
}以上程序執(zhí)行結(jié)果為:
[18 44 1 41 92 143 194 245 40 240 63]
18 300 1.01
1
300
70000
2000000000
500000000000
1
300
70000
2000000000
500000000000
100
100
100
100
100
100
100
100
I'm string!
編碼
?gbinary.Encode?方法是一個(gè)非常強(qiáng)大靈活的方法,可以將所有的基本類型轉(zhuǎn)換為二進(jìn)制類型(?[ ]byte?)。在?gbinary.Encode?方法內(nèi)部,會(huì)自動(dòng)對(duì)變量進(jìn)行長度計(jì)算,采用最小二進(jìn)制長度來存放該變量的二進(jìn)制值。例如,針對(duì)int類型值為1的變量,?gbinary.Encode?將只會(huì)用1個(gè)byte來存儲(chǔ),而int類型值為300的變量,將會(huì)使用2個(gè)byte來存儲(chǔ),盡量減少二進(jìn)制結(jié)果的存儲(chǔ)空間。因此,在解析的時(shí)候要非常注意?[ ]byte?的長度,建議能夠確定變量長度的地方,在進(jìn)行二進(jìn)制編碼/解碼時(shí),盡量采用形如int8/16/32/64的定長基本類型來存儲(chǔ)變量,這樣解析的時(shí)候也能夠采用對(duì)應(yīng)的變量形式進(jìn)行解析,不易產(chǎn)生錯(cuò)誤。
?gbinary?包也提供了一系列?gbinary.Encode*?的方法,用于將基本數(shù)據(jù)類型轉(zhuǎn)換為二進(jìn)制。其中,?gbinary.EncodeInt/gbinary.EncodeUint?也是會(huì)在內(nèi)部自動(dòng)識(shí)別變量值大小,返回不定長度的?[ ]byte?值,長度范圍1/2/4/8。
解碼
在二進(jìn)制類型的解析操作中,二進(jìn)制的長度(?[ ]byte?的長度)是非常重要的,只有給定正確的長度才能執(zhí)行正確的解析,因此?gbinary.Decode?方法給定的變量長度必須為確定長度類型的變量,例如:int8/16/32/64、uint8/16/32/64、float32/64,而如果給定的第二個(gè)變量地址對(duì)應(yīng)的變量類型為int/uint,無法確定長度,因此解析會(huì)失敗。
此外,?gbinary?包也提供了一系列?gbinary.DecodeTo*?的方法,用于將二進(jìn)制轉(zhuǎn)換為特定的數(shù)據(jù)類型。其中,?gbinary.DecodeToInt/gbinary.DecodeToUint?方法會(huì)對(duì)二進(jìn)制長度進(jìn)行自動(dòng)識(shí)別解析,支持的二進(jìn)制參數(shù)長度范圍1-8。
按位操作處理示例
?gbinary?的Bits相關(guān)操作簡化了底層二進(jìn)制位操作的復(fù)雜度,為精準(zhǔn)的數(shù)據(jù)按位處理提供了可能。
批量傳感器狀態(tài)數(shù)據(jù)上報(bào)示例
例如,針對(duì)于物聯(lián)網(wǎng)項(xiàng)目而言,傳感器設(shè)備是比較常見的硬件設(shè)備,我們以下的示例展示了網(wǎng)關(guān)向平臺(tái)上報(bào)其下管理的傳感器的狀態(tài)信息。由于傳感器狀態(tài)只有4種(0:已下線,1:開啟, 2:關(guān)閉, 3:待機(jī)),正好對(duì)應(yīng)了2個(gè)二進(jìn)制位(2 bit),因此1byte(8 bit)便可以表示出4個(gè)傳感器設(shè)備的狀態(tài)。
看以下的例子,用以上報(bào)平臺(tái)100個(gè)傳感器已開啟,上報(bào)的狀態(tài)順序便是傳感器在網(wǎng)關(guān)下端口順序(索引從0開始):
https://github.com/gogf/gf/v2/blob/master/.example/encoding/gbinary/bits1.go
package main
import (
"fmt"
"github.com/gogf/gf/v2/encoding/gbinary"
)
func main() {
// 傳感器狀態(tài),0:已下線, 1:開啟, 2:關(guān)閉, 3:待機(jī)
count := 100
status := 1
// 網(wǎng)關(guān)編碼
bits := make([]gbinary.Bit, 0)
for i := 0; i < count; i++ {
bits = gbinary.EncodeBits(bits, int(status), 2)
}
buffer := gbinary.EncodeBitsToBytes(bits)
fmt.Println("buffer length:", len(buffer))
/* 上報(bào)過程忽略,這里只展示編碼/解碼示例 */
// 平臺(tái)解碼
alivecount := 0
sensorbits := gbinary.DecodeBytesToBits(buffer)
for i := 0; i < len(sensorbits); i += 2 {
if gbinary.DecodeBits(sensorbits[i:i+2]) == 1 {
alivecount++
}
}
fmt.Println("alived sensor:", alivecount)
}執(zhí)行后輸出結(jié)果為:
buffer length: 25
alived sensor: 100可以看到,上報(bào)100個(gè)傳感器的狀態(tài)數(shù)據(jù)只需要25byte即可,該示例中我們?cè)谄脚_(tái)上解碼后統(tǒng)計(jì)開啟的傳感器數(shù)量有100臺(tái)。
gkvdb數(shù)據(jù)庫META數(shù)據(jù)結(jié)構(gòu)操作示例
我們?cè)倏纯匆粋€(gè)實(shí)戰(zhàn)的例子。?gkvdb?是?gf?框架相同作者開發(fā)的基于?DRH?算法的高性能?Key-Value?嵌入式數(shù)據(jù)庫,其中元數(shù)據(jù)的存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)如下:
[鍵名哈希64(64bit,8byte) 鍵名長度(8bit,1byte) 鍵值長度(24bit,3byte) 數(shù)據(jù)文件偏移量(40bit,5byte)](變長)我們使用一條元數(shù)據(jù)來演示編碼/解碼操作。
github.com/gogf/gf/v2/blob/master/.example/encoding/gbinary/bits2.go
package main
import (
"fmt"
"github.com/gogf/gf/v2/encoding/gbinary"
)
func main() {
// Meta元數(shù)據(jù)文件數(shù)據(jù)結(jié)構(gòu):[鍵名哈希64(64bit,8byte) 鍵名長度(8bit,1byte) 鍵值長度(24bit,3byte) 數(shù)據(jù)文件偏移量(40bit,5byte)](變長)
hash := 521369841259754125
klen := 12
vlen := 35535
offset := 80000000
// 編碼
bits := make([]gbinary.Bit, 0)
bits = gbinary.EncodeBits(bits, hash, 64)
bits = gbinary.EncodeBits(bits, klen, 8)
bits = gbinary.EncodeBits(bits, vlen, 24)
bits = gbinary.EncodeBits(bits, offset, 40)
buffer := gbinary.EncodeBitsToBytes(bits)
fmt.Println("meta length:", len(buffer))
/* 文件存儲(chǔ)及數(shù)據(jù)查詢過程忽略,這里只展示元數(shù)據(jù)編碼/解碼示例 */
// 解碼
metabits := gbinary.DecodeBytesToBits(buffer)
fmt.Println("hash :", gbinary.DecodeBits(metabits[0 : 64]))
fmt.Println("klen :", gbinary.DecodeBits(metabits[64 : 72]))
fmt.Println("vlen :", gbinary.DecodeBits(metabits[72 : 96]))
fmt.Println("offset:", gbinary.DecodeBits(metabits[96 : 136]))
}運(yùn)行后,輸出結(jié)果為:
meta length: 17
hash : 521369841259754125
klen : 12
vlen : 35535
offset: 80000000 當(dāng)前文章:創(chuàng)新互聯(lián)GoFrame教程:GoFrame二進(jìn)制編解碼-gbinary
文章出自:http://www.dlmjj.cn/article/ccopgoe.html


咨詢
建站咨詢
