gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 01:21:45 25 4
gpt4 key购买 nike

http://play.golang.org/p/RqScJVvpS7

package main

import (
"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 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

我错过了什么?我本以为这是一个微不足道的变化......

编辑:我刚刚尝试扩展我的缓冲区数组。出于某种奇怪的原因,它起作用了,我得到了 10count。怎么可能? int64 是 64 位 = 8 字节,对吧?

最佳答案

引用 encoding/binary 的文档:

The varint functions encode and decode single integer values using a variable-length encoding; smaller values require fewer bytes. For a specification, see 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 的大小)时才能实现.

具体编码细节在linked page上。

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

关于go - 使用 binary.PutVarint(...) 时索引超出范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32720218/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com