13
\$\begingroup\$

I have a data stream of bytes and I'd like to get a little endian encoded int32 from four bytes. Is there a better way than to do this like the following code?

package main

func read_int32(data []byte) int32 {
    return int32(uint32(data[0]) + uint32(data[1])<<8 + uint32(data[2])<<16 + uint32(data[3])<<24)
}

func main() {
    println(read_int32([]byte{0xFE,0xFF,0xFF,0xFF})) // -2
    println(read_int32([]byte{0xFF,0x00,0x00,0x00})) // 255
}

The code above seems to work fine, but perhaps there is a built-in function in Go that I've missed or there is a super cool hack that does that in one instruction?

\$\endgroup\$
1

2 Answers 2

16
\$\begingroup\$

encoding/binary package may have what you need. Check this: http://golang.org/pkg/encoding/binary/#example_Read

Your code with modified read_int32 function could be:

package main
import (
    "bytes"
    "encoding/binary"
    "fmt"
)

func read_int32(data []byte) (ret int32) {
    buf := bytes.NewBuffer(data)
    binary.Read(buf, binary.LittleEndian, &ret)
    return
}

func main() {
    fmt.Println(read_int32([]byte{0xFE, 0xFF, 0xFF, 0xFF})) // -2
    fmt.Println(read_int32([]byte{0xFF, 0x00, 0x00, 0x00})) // 255
}

Also you can interpret big endian by replacing binary.LittleEndian with binary.BigEndian

\$\endgroup\$
1
  • \$\begingroup\$ That looks fine, I'll try it out and report back. Thanks! \$\endgroup\$
    – topskip
    Nov 3, 2012 at 7:29
3
\$\begingroup\$

This is a really late answer, however there are 2 different ways to do it.

func readInt32(b []byte) int32 {
    // equivalnt of return int32(binary.LittleEndian.Uint32(b))
    return int32(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
}

// this is much faster and more efficient, however it won't work on appengine 
// since it doesn't have the unsafe package.
// Also this would blow up silently if len(b) < 4.
func ReadInt32Unsafe(b []byte) int32 {
    return *(*int32)(unsafe.Pointer(&b[0]))
}
\$\endgroup\$
4
  • \$\begingroup\$ How to modify func readInt32 to return float32 value? I'd tried to just change return int32(...) to retrun float32(...) and get wrong data. \$\endgroup\$
    – Борис
    Apr 8, 2015 at 14:36
  • 1
    \$\begingroup\$ @Борис, replace int32 with math.Float32frombits. See here. Internally, it uses the unsafe cast, but is safe because it operates on a uint32 instead of a slice. \$\endgroup\$
    – George
    Jan 3, 2016 at 19:29
  • \$\begingroup\$ how do you convert an int into []byte ? \$\endgroup\$
    – Teocci
    Nov 30, 2021 at 4:48
  • \$\begingroup\$ The ReadInt32Unsafe approach is neither faster nor correct. It breaks on big endian platforms and on little endian platforms, a smart compiler will generate essentially the same code for both. \$\endgroup\$
    – FUZxxl
    Jan 3, 2022 at 13:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.