GoLang按位计算

时间:2015-02-11 21:43:57

标签: go bitwise-operators

我有一个缓冲区:

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,
    })

我试图返回缓冲区的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.....)))

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

1 个答案:

答案 0 :(得分:2)

您必须进行手动位移和“删除”,但可以通过删除所有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)
....