将[32]字节转换为[8] uint32

时间:2017-05-07 09:37:02

标签: arrays go type-conversion slice

我在[32]byte中存储了256位。

我想将其转换为[8]uint32,第一个uint32存储前四个字节等。

我打算写一个函数,通过将位移到正确的位置等来实现这一点,我想知道在Go中有更简单的方法吗?

2 个答案:

答案 0 :(得分:9)

使用binary.ByteOrder

encoding/binary包使其变得简单,binary.ByteOrder接口类型的值可用于从字节切片中读取uint32值。有一个binary.LittleEndian导出变量,您可以直接使用它。将它放在一个简单的for循环中以读取所有8个值:

data := [32]byte{1, 0, 0, 0, 2}
ints := [8]uint32{}

for i := 0; i < len(data); i += 4 {
    ints[i/4] = binary.LittleEndian.Uint32(data[i:])
}

fmt.Println(ints)

输出(在Go Playground上尝试):

[1 2 0 0 0 0 0 0]

这当然适用于任意数量的字节(4的倍数),而不仅仅是32。

使用binary.Read()

另一个更短的选择是使用binary.Read()

func Read(r io.Reader, order ByteOrder, data interface{}) error

这当然需要io.Reader,您可以使用bytes.NewBuffer()。这种转换方式很简单:

data := [32]byte{1, 0, 0, 0, 2}
ints := [8]uint32{}

err := binary.Read(bytes.NewBuffer(data[:]), binary.LittleEndian, &ints)

fmt.Println(ints, err)

输出(在Go Playground上尝试):

[1 2 0 0 0 0 0 0] <nil>

使用unsafe.Pointer

为了完整性,这是另一种不安全的方式。由于数组按顺序排列在内存中,因此两个数组都占用相同的大小。我们可以将输入的内存区域解释为输出类型的值:

data := [32]byte{1, 0, 0, 0, 2}
ints := [8]uint32{}

ints = *(*[8]uint32)((unsafe.Pointer)(&data))

fmt.Println(ints)

输出(在Go Playground上尝试):

[1 2 0 0 0 0 0 0]

这是解决任务的最有效和最不安全的方式。

在这种情况下,可以像呈现一样安全,但请谨慎使用包unsafe并作为最后的手段。许多其他看似非常相似的案例可能无效。我们“幸运”,因为我们有数组输入以小端字节顺序给出,但是使用切片和/或不同的字节顺序,它将是一个不同的故事。上面介绍的其他两种方法更为通用,可以使用切片和数组。

答案 1 :(得分:1)

似乎我可以使用类似的东西来做到这一点:

data_uint32[0] = binary.LittleEndian.Uint32(data_bytes[0:4])
data_uint32[1] = binary.LittleEndian.Uint32(data_bytes[4:8])
data_uint32[2] = binary.LittleEndian.Uint32(data_bytes[8:12])
data_uint32[3] = binary.LittleEndian.Uint32(data_bytes[12:16])
data_uint32[4] = binary.LittleEndian.Uint32(data_bytes[16:20])
data_uint32[5] = binary.LittleEndian.Uint32(data_bytes[20:24])
data_uint32[6] = binary.LittleEndian.Uint32(data_bytes[24:28])
data_uint32[7] = binary.LittleEndian.Uint32(data_bytes[28:32])

也许有一种更简单的方法,但现在这样做。