golang中encoding/binary包

1、golang包中的binary包是什么?
2、binary为我们开发者提供了哪些内容?以及怎么使用?
3、编解码有哪几种方法?

转化成二进制格式与原本数据转字符串相比会更节省空间

一、golang包中的binary包是什么?
此包实现了对数据与byte之间的转换,以及varint的编解码。

二、binary为我们开发者提供了哪些内容?以及怎么使用?
数据的byte序列化转换

func Read(r io.Reader, order ByteOrder, data interface{}) error
func Write(w io.Writer, order ByteOrder, data interface{}) error
func Size(v interface{}) int

uvarint和varint的编解码

func PutUvalint(buf []byte, x uint64) int
func PutVarint(buf []byte, x int64) int
func Uvarint(buf []byte) (uint64, int)
func Varint(buf []byte) (int64, int)
func ReadUvarint(r io.ByteReader) (uint64, error)
func ReadVarint(r io.ByteReader) (int64, error)

结构体

type ByteOrder:可以定义自己的字节序结构,用于序列化和反序列化数据。

1)func Read(r io.Reader, order ByteOrder, data interface{}) error

参数列表:
1)r  可以读出字节流的数据源
2)order  特殊字节序,包中提供大端字节序和小端字节序
3)data  需要解码成的数据
返回值:error  返回错误
功能说明:Read从r中读出字节数据并反序列化成结构数据。data必须是固定长的数据值或固定长数据的slice。从r中读出的数据可以使用特殊的 字节序来解码,并顺序写入value的字段。当填充结构体时,使用(_)名的字段讲被跳过。

代码案例

package main

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

func main() {
    var pi float64
    b := []byte{0x18,0x2d,0x44,0x54,0xfb,0x21,0x09,0x40}
    buf := bytes.NewBuffer(b)
    err := binary.Read(buf, binary.LittleEndian, &pi)
    if err != nil {
        log.Fatalln("binary.Read failed:", err)
    }
    fmt.Println(pi)
}

2)Write(w io.Writer, order ByteOrder, data interface{}) error

参数列表:
1)w  可写入字节流的数据
2)order  特殊字节序,包中提供大端字节序和小端字节序
3)data  需要解码的数据
返回值:error  返回错误
功能说明:
Write讲data序列化成字节流写入w中。data必须是固定长度的数据值或固定长数据的slice,或指向此类数据的指针。写入w的字节流可用特殊的字节序来编码。另外,结构体中的(_)名的字段讲忽略。

代码案例:

package main

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

func main() {
    buf := new(bytes.Buffer)
    pi := math.Pi

    err := binary.Write(buf, binary.LittleEndian, pi)
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(buf.Bytes())
}

3)func Size(v interface{}) int

参数列表:v  需要计算长度的数据
返回值:int 数据序列化之后的字节长度
功能说明:
Size讲返回数据系列化之后的字节长度,数据必须是固定长数据类型、slice和结构体及其指针。

代码实例

package main

import (
    "fmt"
    "encoding/binary"
)

func main() {
    var a int
    p := &a
    b := [10]int64{1}
    s := "adsa"
    bs := make([]byte, 10)

    fmt.Println(binary.Size(a)) // -1
    fmt.Println(binary.Size(p)) // -1
    fmt.Println(binary.Size(b)) // 80
    fmt.Println(binary.Size(s)) // -1
    fmt.Println(binary.Size(bs))    // 10
}

4)func PutUvarint(buf []byte, x uint64) int

参数列表:
1)buf  需写入的缓冲区
2)x  uint64类型数字
返回值:
1)int  写入字节数。
2)panic  buf过小。
功能说明:
PutUvarint主要是讲uint64类型放入buf中,并返回写入的字节数。如果buf过小,PutUvarint将抛出panic。

代码案例

package main

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

func main() {
    u16 := 1234
    u64 := 0x1020304040302010
    sbuf := make([]byte, 4)
    buf := make([]byte, 10)

    ret := binary.PutUvarint(sbuf, uint64(u16))
    fmt.Println(ret, len(strconv.Itoa(u16)), sbuf)

    ret = binary.PutUvarint(buf, uint64(u64))
    fmt.Println(ret, len(strconv.Itoa(u64)), buf)
}
/*
输出结果:
2 4 [210 9 0 0]
9 19 [144 192 192 129 132 136 140 144 16 0]
会发现转成二进制来传输数据,比直接转字符串之后转[]byte这种方式传更节省传输空间
 */

5)func PutVarint(buf []byte, x int64) int

参数列表:
1)buf  需要写入的缓冲区
2)x int64类型数字
返回值:
1)int  写入字节数
2)panic  buf过小
功能说明:
PutVarint主要是讲int64类型放入buf中,并返回写入的字节数。如果buf过小,PutVarint将抛出panic。

代码案例:

package main

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

func main() {
    i16 := 1234
    i64 := -1234567890
    sbuf := make([]byte, 4)
    buf := make([]byte, 10)

    ret := binary.PutVarint(buf, int64(i16))
    fmt.Println(ret, len(strconv.Itoa(i16)), sbuf)

    ret = binary.PutVarint(buf, int64(i64))
    fmt.Println(ret, len(strconv.Itoa(i64)), buf)
}
/*
2 4 [0 0 0 0]
5 11 [163 139 176 153 9 0 0 0 0 0]
 */

6)func Uvarint(buf []byte) (uint64, int)

参数列表:buf  需要解码的缓冲区
返回值:
1)uint64  解码的数据。
2)int  解析的字节数。
功能说明:
Uvarint是从buf中解码并返回一个uint64的数据,及解码的字节数(>0)。如果出错,则返回数据0和一个小于等于0的字节数n,其意义为:
1)n == 0: buf太小
2)n < 0: 数据太大,超出uint64最大范围,且-n为已解析字节数

代码案例

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    sbuf := []byte{}
    buf := []byte{144,192,192,132,136,140,144,16,0,1,1}
    bbuf := []byte{144,192,192,129,132,136,140,144,192,192,1,1}

    num, ret := binary.Uvarint(sbuf)
    fmt.Println(num, ret)

    num, ret = binary.Uvarint(buf)
    fmt.Println(num, ret)

    num, ret = binary.Uvarint(bbuf)
    fmt.Println(num, ret)
}
  1. func Varint(buf []byte) (int64, int)
参数列表: buf  需要解码的缓冲区
返回值:
1) int64 解码的数据
2) int  解析的字节数
功能说明:
Varint是从buf中解码并返回一个int64的数据,及解码的字节数(>0).如果出错,则返回数据0和一个小于等于0的字节数n,其意义为:
1) n == 0: buf太小
2) n < 0: 数据太大,超出64位,且-n为已解析字节数

代码案例

package main

import (
  "encoding/binary"
    "fmt"
)

func main() {
    var sbuf []byte
    var buf []byte = []byte{144, 192, 192, 129, 132, 136, 140, 144, 16, 0, 1, 1}
    var bbuf []byte = []byte{144, 192, 192, 129, 132, 136, 140, 144, 192, 192, 1, 1}

    num, ret := binary.Varint(sbuf)
    fmt.Println(num, ret) //0 0

    num, ret = binary.Varint(buf)
    fmt.Println(num, ret) //580990878187261960 9

    num, ret = binary.Varint(bbuf)
    fmt.Println(num, ret) //0 -11
}
  1. func ReadUvarint(r io.ByteReader) (uint64, error)
参数列表:
返回值:
1) uint64  解析出的数据
2) error  返回的错误
功能说明:
ReadUvarint从r中解析并返回一个uint64类型的数据及出现的错误.
功能说明:
ReadUvarint从r中解析并返回一个uint64类型的数据及出现的错误.

代码案例

package main

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

func main() {
    var sbuf []byte
    var buf []byte = []byte{144, 192, 192, 129, 132, 136, 140, 144, 16, 0, 1, 1}
    var bbuf []byte = []byte{144, 192, 192, 129, 132, 136, 140, 144, 192, 192, 1, 1}

    num, err := binary.ReadUvarint(bytes.NewBuffer(sbuf))
    fmt.Println(num, err) //0 EOF

    num, err = binary.ReadUvarint(bytes.NewBuffer(buf))
    fmt.Println(num, err) //1161981756374523920 <nil>

    num, err = binary.ReadUvarint(bytes.NewBuffer(bbuf))
    fmt.Println(num, err) //4620746270195064848 binary: varint overflows a 64-bit integer
}
  1. func ReadVarint(r io.ByteReader) (int64, error)
参数列表: r  实现ByteReader接口的对象
返回值: 
1) int64  解析出的数据
2) error  返回的错误
功能说明:
ReadVarint从r中解析并返回一个int64类型的数据及出现的错误.

代码案例

package main

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

func main() {
    var sbuf []byte
    var buf []byte = []byte{144, 192, 192, 129, 132, 136, 140, 144, 16, 0, 1, 1}
    var bbuf []byte = []byte{144, 192, 192, 129, 132, 136, 140, 144, 192, 192, 1, 1}

    num, err := binary.ReadVarint(bytes.NewBuffer(sbuf))
    fmt.Println(num, err) //0 EOF

    num, err = binary.ReadVarint(bytes.NewBuffer(buf))
    fmt.Println(num, err) //580990878187261960 <nil>

    num, err = binary.ReadVarint(bytes.NewBuffer(bbuf))
    fmt.Println(num, err) //2310373135097532424 binary: varint overflows a 64-bit integer
}

三、编解码有哪几种方法?
编码

  1. func Write(w io.Writer, order ByteOrder, data interface{}) error
  2. func PutUvarint(buf []byte, x uint64) int
  3. func PutVarint(buf []byte, x int64) int

解析
1)func Uvarint(buf []byte) (uint64, int)
2)func Varint(buf []byte) (int64, int)
3)func ReadUvarint(r io.ByteReader) (uint64, error)
4)func ReadVarint(r io.ByteReader) (int64, error)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容