【发布时间】:2014-02-18 19:32:40
【问题描述】:
我有一个长度为 4 的切片存储了一个这样的 int 值:
[159 124 0 0]
然后我尝试了val, encodeBytes := binary.Uvarint(slice),但是错了val:
val = 15903, encodebytes = 2
正确的val应该是31903,有什么问题?
代码如下:
【问题讨论】:
标签: go
我有一个长度为 4 的切片存储了一个这样的 int 值:
[159 124 0 0]
然后我尝试了val, encodeBytes := binary.Uvarint(slice),但是错了val:
val = 15903, encodebytes = 2
正确的val应该是31903,有什么问题?
代码如下:
【问题讨论】:
标签: go
根据二进制包文档,用于解释字节序列的编码是available here。它指定字节被解释为:
varint 中的每个字节,除了最后一个字节,都有最重要的 bit (msb) set——这表明还有更多字节要到来。 每个字节的低 7 位用于存储二进制补码 以 7 位为一组表示数字,最低有效 先分组。
[159 124 0 0] 的二进制表示为:
1001 1111 , 0111 1100 , 0000 0000, 0000 0000
第一个字节的最高有效位 (MSB) 已设置,因此第二个字节也将被解释。第二个字节 MSB 未设置,因此忽略其余字节。
通过删除字节的 MSB 来解释我们得到的位:
001 1111 , 111 1100
这两个组然后在被解释为数字之前被反转:
111 1100 , 001 1111
concatenated:
0011 1110 0001 1111
将其转换回十进制我们得到:
1 + 2 +4 + 8 + 16 + 0 + 0 + 0 + 0 + 512 + 1024 + 2048 + 4096 + 8192 = 15903
正如 James 和 peterSO 的帖子所表明的那样,您可能想改用 binary.LittleEndian.Uint32。
【讨论】:
例如,
package main
import (
"encoding/binary"
"fmt"
)
func main() {
bytes := []byte{159, 124, 0, 0}
integer := int(binary.LittleEndian.Uint32(bytes))
fmt.Println(bytes, integer)
}
输出:
[159 124 0 0] 31903
【讨论】:
从预期的结果来看,听起来您正在尝试解码一个小端序的 32 位整数。 binary.Uvarint 函数不适合这项工作,因为它解码了 Protocol Buffers 规范使用的可变长度整数编码。
请尝试使用binary.LittleEndian.Uint32():
val := binary.LittleEndian.Uint32(slice)
【讨论】: