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?

+3


source to share


2 answers


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.

+9


source


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.

+1


source







All Articles