9
\$\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?

| improve this question | | | | |
\$\endgroup\$
12
\$\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

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ That looks fine, I'll try it out and report back. Thanks! \$\endgroup\$ – topskip Nov 3 '12 at 7:29
2
\$\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]))
}
| improve this answer | | | | |
\$\endgroup\$
  • \$\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 '15 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 '16 at 19:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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