将[8]字节转换为uint64

Ale*_*uer 12 go

所有.我遇到了一个似乎很奇怪的问题.(可能是我睡着了很久,我忽略了一些显而易见的事情.)

[]byte由于某些十六进制解码,我的长度为8.我需要生产一个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)
}
Run Code Online (Sandbox Code Playgroud)

这是在play.golang.org上.

当它运行时,它显示numas 0,即使它是十六进制,它应该是000108000801ab01.此外,如果一个人从中获取第二个值binary.Uvarint(),那么它是从缓冲区读取的字节数,据我所知,它应该是8,即使它实际上是1.

我在解释这个错误吗?如果是这样,我应该使用什么呢?

谢谢,大家好.:)

Den*_*ret 16

您正在使用一个函数进行解码,该函数的使用不是您需要的函数:

Varints是一种使用一个或多个字节编码整数的方法; 绝对值较小的数字占用较少的字节数.有关规范,请参阅 http://code.google.com/apis/protocolbuffers/docs/encoding.html.

它不是标准编码,而是非常具体的可变字节数编码.这就是为什么它在第一个字节停止,其值小于0x080.

正如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
}
Run Code Online (Sandbox Code Playgroud)

所以你可以使用

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)
}
Run Code Online (Sandbox Code Playgroud)

或者(如果你想检查错误而不是恐慌,感谢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)
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以通过`num:= binary.LittleEndian.Uint64(array)来避免Read()和bytes.Buffer. (3认同)
  • 应该注意的是,如果输入缓冲区不足以容纳完整的请求数据类型,这些快捷方法将会出现混乱.使用`binary.Read`方法会给你一个'错误'返回,你可以检查. (2认同)