为了账号安全,请及时绑定邮箱和手机立即绑定

使用 binary.PutVarint(...) 时索引超出范围

使用 binary.PutVarint(...) 时索引超出范围

Go
慕村225694 2021-11-08 17:02:30
http://play.golang.org/p/RqScJVvpS7package mainimport (    "fmt"    "math/rand"    "encoding/binary")func main() {    buffer := []byte{0, 0, 0, 0, 0, 0, 0, 0}    num := rand.Int63()    count := binary.PutVarint(buffer, num)    fmt.Println(count)}前一段时间我有这个工作,num当时只是一个递增uint64,我正在使用binary.PutUvarint但现在它是一个随机的 int64 并且binary.PutVarint我收到一个错误:panic: runtime error: index out of rangegoroutine 1 [running]:encoding/binary.PutUvarint(0x1042bf58, 0x8, 0x8, 0x6ccb, 0xff9faa4, 0x9acb0442, 0x7fcfd52, 0x4d658221)    /usr/local/go/src/encoding/binary/varint.go:44 +0xc0encoding/binary.PutVarint(0x1042bf58, 0x8, 0x8, 0x6ccb, 0x7fcfd52, 0x4d658221, 0x14f9e0, 0x104000e0)    /usr/local/go/src/encoding/binary/varint.go:83 +0x60main.main()    /tmp/sandbox010341234/main.go:12 +0x100我错过了什么?我会认为这是一个微不足道的改变......编辑:我只是尝试扩展我的缓冲区数组。对于一些奇怪的原因,它的工作原理和我获得count的10。怎么可能?int64是 64 位 = 8 字节,对吗?
查看完整描述

1 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

引用文档encoding/binary:


varint 函数使用可变长度编码对单个整数值进行编码和解码;较小的值需要较少的字节。有关规范,请参阅https://developers.google.com/protocol-buffers/docs/encoding。


所以这binary.PutVarint()不是固定的,而是可变长度的编码。传递 时int64,大数需要 8 个字节以上,小数需要 8 个字节以下。由于您编码的数字是一个随机数,因此即使在其最高字节中也会有随机位。


看这个简单的例子:


buffer := make([]byte, 100)

for num := int64(1); num < 1<<60; num <<= 4 {

    count := binary.PutVarint(buffer, num)

    fmt.Printf("Num=%d, bytes=%d\n", num, count)

}

输出:


Num=1, bytes=1

Num=16, bytes=1

Num=256, bytes=2

Num=4096, bytes=2

Num=65536, bytes=3

Num=1048576, bytes=4

Num=16777216, bytes=4

Num=268435456, bytes=5

Num=4294967296, bytes=5

Num=68719476736, bytes=6

Num=1099511627776, bytes=6

Num=17592186044416, bytes=7

Num=281474976710656, bytes=8

Num=4503599627370496, bytes=8

Num=72057594037927936, bytes=9

可变长度编码的本质是小数字使用较少的字节,但这只能在大数字可能使用超过 8 个字节的情况下才能实现(即大小为int64)。


具体编码的详细信息在链接页面上。


一个非常简单的例子是:一个字节是 8 位。使用输出字节的 7 位作为“有用”位来编码数据/数字。如果最高位为 1,则意味着需要更多字节。如果最高位为 0,我们就完成了。你可以看到,小的数字可以使用1个输出字节编码(如n=10),而我们使用1个额外位,每7位有用的数据,因此,如果输入的号码使用所有64位,我们将结束与更多8 字节以上:需要 10 组来覆盖 64 位,因此我们将需要 10 字节(9 组仅 9*7=63 位)。


查看完整回答
反对 回复 2021-11-08
  • 1 回答
  • 0 关注
  • 268 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信