Go 使用binary.PutVarient(…)时索引超出范围
不久前,当Go 使用binary.PutVarient(…)时索引超出范围,go,Go,不久前,当num只是一个递增的uint64时,我使用了binary.PutUvarint但现在它是一个随机的int64和二进制。PutVarint我得到一个错误: panic: runtime error: index out of range goroutine 1 [running]: encoding/binary.PutUvarint(0x1042bf58, 0x8, 0x8, 0x6ccb, 0xff9faa4, 0x9acb0442, 0x7fcfd52, 0x4d658221)
num
只是一个递增的uint64
时,我使用了binary.PutUvarint
但现在它是一个随机的int64和二进制。PutVarint
我得到一个错误:
panic: runtime error: index out of range
goroutine 1 [running]:
encoding/binary.PutUvarint(0x1042bf58, 0x8, 0x8, 0x6ccb, 0xff9faa4, 0x9acb0442, 0x7fcfd52, 0x4d658221)
/usr/local/go/src/encoding/binary/varint.go:44 +0xc0
encoding/binary.PutVarint(0x1042bf58, 0x8, 0x8, 0x6ccb, 0x7fcfd52, 0x4d658221, 0x14f9e0, 0x104000e0)
/usr/local/go/src/encoding/binary/varint.go:83 +0x60
main.main()
/tmp/sandbox010341234/main.go:12 +0x100
我错过了什么?我会认为这是一个微不足道的改变
编辑:我刚刚尝试扩展我的缓冲区数组。出于某种奇怪的原因,它起作用了,我得到了计数的10
。这怎么可能int64
是64位=8字节,对吗?引用以下文件:
varint函数使用变长编码对单个整数值进行编码和解码;较小的值需要较少的字节。有关规范,请参阅
因此,编码不是固定的,而是可变长度的编码。当传递一个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)
}
可变长度编码的本质是小数字使用更少的字节,但这只能在大数字可能使用超过8个字节(即int64
的大小)的情况下实现
有关特定编码的详细信息,请参阅
一个非常简单的例子是:一个字节是8位。使用输出字节的7位作为“有用”位对数据/数字进行编码。如果最高位为1,则意味着需要更多字节。如果最高位是0,我们就完成了。您可以看到,小数字可以使用1个输出字节(例如,n=10
)进行编码,而我们每7位有用数据使用1个额外的位,因此如果输入数字使用所有64位,我们将得到超过8个字节:需要10个组来覆盖64位,因此我们将需要10个字节(9个组仅为9*7=63位).但是rand.Int63()
返回一个int64
,定义为8字节,对吗?它怎么可能需要10个呢?@CoreyOgburn:Varint是一种可变长度编码。你想要字节顺序。putunit64
,或者仅仅是二进制。写
。我在质疑我的理智。一个int64,一个64位=8字节的值怎么会产生10个字节?“可变长度编码”听起来应该可以存储最多8个字节,如果它是一个小值,则可以存储更少的字节。@CoreyOgburn请参阅编辑后的答案,了解10字节输出的简单可变长度编码和推理。我认为转换必须添加一些内容,但我希望它的行为类似于字节顺序。putunit64
。我假设“可变长度”意味着最多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