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