GoLang 按位计算

GoLang bitwise calculation

我有一个缓冲区:

buffer := bytes.NewBuffer([]byte{
        0x85, 0x02, 0xFF, 0xFF,
        0x00, 0x01, 0x00, 0x02,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x03,
        0x41, 0x42, 0x43,
    })

我正在尝试 return 缓冲区的 int 值 [8:24] 我得到

[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]

不确定如何移动这么大的部分。的字节。

新手。任何帮助都会很棒。我最初的方法是

requestid := (uint64(buffer.Bytes()[8]&0xff)<<24 + uint64(buffer.Bytes()[9]&0xff)<<16 + uint64(buffer.Bytes()[10]&0xff)<<8 + uint64(buffer.Bytes()[11]&0xff.....)))

但这很乏味,我知道必须有更简单的方法。

您必须手动进行移位和 OR'ing,但可以通过删除所有这些 buffer.Bytes() 调用来清理您的代码。

您也不需要 &0xff 部分。 n&0xff 所做的是清除 0-255 范围之外的所有位。由于缓冲区中的每个值已经是一个字节 (0-255),因此这些操作根本不执行任何操作。如果我们想做 22 & 255,我们会得到以下结果:

    Hexadecimal   | Decimal     | Binary
    --------------|-------------|----------------------
x   0x16          | 22          | 00010110
y   0xff          | 255         | 11111111
    --------------|-------------|---------------------- AND (&)
    0x16          | 22          | 00010110 = x

如您所见,操作完全没有效果。将 x 替换为任何 8 位值,您将看到相同的结果。 x & 0xff 的结果总是 x.

此外,当您分配给 requestId 时,您首先要移动 24 位。这告诉我你正在读取一个 32 位整数。为什么还要继续读取超过 32 位的值并将其全部转换为 64 位整数?

如果您正在读取 Big Endian 中的 64 位 int,试试这个:

data := buf.Bytes()[8:]
requestid := uint64(data[0])<<56 | uint64(data[1])<<48 |
    uint64(data[2])<<40 | uint64(data[3])<<32 |
    uint64(data[4])<<24 | uint64(data[5])<<16 |
    uint64(data[6])<<8 | uint64(data[7])

如果您正在 Little Endian 中读取 64 位 int,试试这个:

data := buf.Bytes()[8:]
requestid := uint64(data[7])<<56 | uint64(data[6])<<48 |
    uint64(data[5])<<40 | uint64(data[4])<<32 |
    uint64(data[3])<<24 | uint64(data[2])<<16 |
    uint64(data[1])<<8 | uint64(data[0])

如果您正在读取 Big Endian 中的 32 位 int,试试这个:

data := buf.Bytes()[8:]
requestid := uint32(data[0])<<24 | uint32(data[1])<<16 |
    uint32(data[2])<<8 | uint32(data[3])

如果您正在使用 Little Endian 读取 32 位 int,试试这个:

data := buf.Bytes()[8:]
requestid := uint32(data[3])<<24 | uint32(data[2])<<16 |
    uint32(data[1])<<8 | uint32(data[0])

二进制包

或者,您可以使用 encoding/binary 包:

var value uint64
err := binary.Read(buf, binary.LittleEndian, &value)
....