Go语言 将[8]字节转换为uint64

mum43rcc  于 2023-11-14  发布在  Go
关注(0)|答案(3)|浏览(147)

我遇到了一个似乎很奇怪的问题。(可能是我早就应该睡觉了,我忽略了一些明显的东西。)
我有一个长度为8的[]byte作为一些十六进制解码的结果。为了使用它,我需要产生一个uint64。我已经尝试使用binary.Uvarint(),从encoding/binary这样做,但它似乎只使用数组中的第一个字节。考虑下面的例子。

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    array := []byte{0x00, 0x01, 0x08, 0x00, 0x08, 0x01, 0xab, 0x01}
    num, _ := binary.Uvarint(array[0:8])
    fmt.Printf("%v, %x\n", array, num)
}

字符串

Here it is on play.golang.org.

当它运行时,它将num显示为0,即使在十六进制中,它应该是000108000801ab01。此外,如果从binary.Uvarint()中捕获第二个值,则它是从缓冲区读取的字节数,据我所知,应该是8,即使它实际上是1。
我理解错了吗?如果是的话,我应该用什么来代替?
谢谢大家:)

qc6wkl3g

qc6wkl3g1#

你正在使用一个函数进行解码,而这个函数的用途不是你需要的:
变量类型是一种使用一个或多个字节对整数进行编码的方法;具有较小绝对值的数字占用较少的字节数。有关规范,请参见http://code.google.com/apis/protocolbuffers/docs/encoding.html
这不是标准编码,而是一种非常特殊的可变字节数编码,这就是为什么它在第一个值小于0x 080的字节处停止。
正如Stephen所指出的,binary.BigEndian和binary.LittleEndian提供了有用的函数来直接解码:

type ByteOrder interface {
    Uint16([]byte) uint16
    Uint32([]byte) uint32
    Uint64([]byte) uint64
    PutUint16([]byte, uint16)
    PutUint32([]byte, uint32)
    PutUint64([]byte, uint64)
    String() string
}

字符串
所以你可以用

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    array := []byte{0x00, 0x01, 0x08, 0x00, 0x08, 0x01, 0xab, 0x01}
    num := binary.LittleEndian.Uint64(array)
    fmt.Printf("%v, %x", array, num)
}


或者(如果你想检查错误而不是恐慌,感谢jimt用直接解决方案指出这个问题):

package main

import (
    "encoding/binary"
    "bytes"
    "fmt"
)

func main() {
    array := []byte{0x00, 0x01, 0x08, 0x00, 0x08, 0x01, 0xab, 0x01}
    var num uint64
    err := binary.Read(bytes.NewBuffer(array[:]), binary.LittleEndian, &num)
    fmt.Printf("%v, %x", array, num)
}

oipij1gg

oipij1gg2#

如果不关心字节顺序,你可以试试这个:

arr := [8]byte{1,2,3,4,5,6,7,8}
num := *(*uint64)(unsafe.Pointer(&arr[0]))

字符串
http://play.golang.org/p/aM2r40ANQC

xdnvmnnf

xdnvmnnf3#

如果你看一下Uvarint的函数,你会发现它并不像你期望的那样是一个直接的转换。
老实说,我还没有弄清楚它需要什么样的字节格式(参见编辑)。
但是写你自己的几乎是微不足道的:

func Uvarint(buf []byte) (x uint64) {
    for i, b := range buf {
        x = x << 8 + uint64(b)
        if i == 7 {
            return
        }
    }
    return
}

字符串

编辑

字节格式是我不熟悉的。它是一种可变宽度编码,每个字节的最高位是一个标志。
如果设置为0,则该字节是序列中的最后一个。
如果设置为1,则编码应继续下一个字节。
只有每个字节的低7位用于构建uint 64值。第一个字节将设置uint 64的低7位,随后的字节位8-15等。

相关问题