Go Varint 返回预期值的一半

标签 go

为什么这段代码的输出是:

package main

import (
    "fmt"
    "encoding/binary"
)

func main() {
    var myByte byte = 18
    array := []byte{myByte}
    val, n := binary.Varint(array)
    fmt.Printf("value: %d, num bytes: %d\n", val, n)
}

value: 9, num bytes: 1 而不是 value: 18, num bytes: 1

这可能与二进制补码有关,但我不知道如何。

最佳答案

TLDR:使用 Uvarint 方法正确解码 unsigned 字节 .. 这就是 byte默认情况下。

字节是无符号存储的(默认情况下字节是无符号的 - 它是 uint8 的别名......在大多数语言中)。

当您解码数字时,您正在调用 binary.Varint .. 它解码一个带符号的数字。由于符号位,这会导致数字不正确。

使用binary.Uvarint ..即解码一个无符号数,你得到正确的结果:

val, n := binary.Uvarint(array) // val = 18, n = 1

扩展示例:

让我们看一下您的数字 - 18。在二进制中,它是这样的:

00010010

binary.Varint 函数如下:

func Varint(buf []byte) (int64, int) {
    ux, n := Uvarint(buf) // ok to continue in presence of error
    x := int64(ux >> 1)
    if ux&1 != 0 {
        x = ^x
    }
    return x, n
}

基本上,它会首先获取您提供的无符号值:18

然后它将所有字节移动 1。这导致:

00001001

那是9的二进制表示。注意符号位仍然是 0——这意味着一个正数。然后它检查是否通过按位与原始值 (18) 与 1 来反转结果。它这样做是因为它在“我知道这个数字已签名”上下文中运行 - 这就是该函数存在的原因:

00010010
00000001
--------
00000000
     = 0

此时,零确实等于零 - 因此该方法返回 x - 即 9。

让我们试试 1

使用 1 作为输入:

00000001

右移:

00000000

AND 原始数字 (1) 为 1:

00000001
00000001
--------
     = 1

在这一点上,结果不等于 0.. 所以结果是反转的:

11111111

这是 -1 的符号表示(注意符号位现在是 1 .. 表示负数)。

关于Go Varint 返回预期值的一半,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28036560/

相关文章:

go - Hyperledger Fabric Chaincode 在执行期间面临错误

去吧,没有得到字符串值

go - 删除redis集群中的多个key

go - 将 int8 放入字节数组

go - 我们如何确定 "last"工作进程/线程在 Go 中何时完成?

go - 如何使用 Golang 查找以 root 身份执行程序的用户?

elasticsearch - 如何在 Golang 中使用 Olivere 将数据插入 Elasticsearch

go - 如何使用 Golang 截取网站的屏幕截图?

io - 多次从 Reader 读取

go - 如何检查特定的golang net/http错误代码?