Convert [32] bytes to [8] uint32
I have 256 bits stored in [32]byte
.
I want to convert this to [8]uint32
, with the first one uint32
holding the first four bytes, etc.
I'm about to write a function that does this by shifting bits to the correct positions etc., I wonder if there is an easier way to do this in Go?
source to share
Using binary.ByteOrder
The package encoding/binary
makes it easier, values binary.ByteOrder
can be used to read values uint32
from bytes bytes. There is an exported variable binary.LittleEndian
that you can use out of the box. Put this in a simple loop for
to read all 8 values:
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)
Output (try on Go Playground ):
[1 2 0 0 0 0 0 0]
And this of course works for any number of bytes (multiple of 4), not just 32.
Using binary.Read()
Another, even shorter alternative is to use binary.Read()
:
func Read(r io.Reader, order ByteOrder, data interface{}) error
This of course requires io.Reader
which you can use bytes.NewBuffer()
. So the conversion is a simple string:
data := [32]byte{1, 0, 0, 0, 2} ints := [8]uint32{} err := binary.Read(bytes.NewBuffer(data[:]), binary.LittleEndian, &ints) fmt.Println(ints, err)
Output (try on Go Playground ):
[1 2 0 0 0 0 0 0] <nil>
Using unsafe.Pointer
For completeness, here's another, unsafe way. Since the arrays are laid out sequentially in memory, both arrays are the same size. We can interpret the input memory area as an output type value:
data := [32]byte{1, 0, 0, 0, 2} ints := [8]uint32{} ints = *(*[8]uint32)((unsafe.Pointer)(&data)) fmt.Println(ints)
Output (try on Go Playground ):
[1 2 0 0 0 0 0 0]
This is the most efficient and most unsafe way to solve your problem.
In this case, it is safe to do so as presented, but use the package unsafe
with caution and as a last resort. Many other seemingly very similar cases may not work. We were "happy" because we had arrays and the input was in least significant byte order, but with chunks and / or different byte ordering, that would be a different story. The above two other methods are more general and work with both slices and arrays.
source to share
I seem to be able to do it using something like:
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])
Perhaps there is an even easier way, but for now it will be done.
source to share