You can use encoding/binary's ByteOrder to do this for 16, 32, 64 bit types
Play
package main
import "fmt"
import "encoding/binary"
func main() {
var mySlice = []byte{244, 244, 244, 244, 244, 244, 244, 244}
data := binary.BigEndian.Uint64(mySlice)
fmt.Println(data)
}
Answer from David Budworth on Stack OverflowYou can use encoding/binary's ByteOrder to do this for 16, 32, 64 bit types
Play
package main
import "fmt"
import "encoding/binary"
func main() {
var mySlice = []byte{244, 244, 244, 244, 244, 244, 244, 244}
data := binary.BigEndian.Uint64(mySlice)
fmt.Println(data)
}
If []byte is ASCII byte numbers then first convert the []byte to string and use the strconv package Atoi method which convert string to int.
package main
import (
"fmt"
"strconv"
)
func main() {
byteNumber := []byte("14")
byteToInt, _ := strconv.Atoi(string(byteNumber))
fmt.Println(byteToInt)
}
Go playground
How do I convert a single byte to int in Go?
How do I convert four bytes to an int32 or uint32?
How do I convert []byte("123") to an integer?
Hi everyone,
I just started using Go today, and am having trouble converting bytes read from a file into integers. I usually code in higher level languages like Python and JavaScript.
I've already seen several StackOverflow threads on this but they're fairly old and none of the suggestions have worked so far.
Specifically, what I'm trying to do is read a BigEndian 16bit signed integer. I'll also need to read int8, int32, and Uint8 eventually.
I've tried using:
binary.Read
binary.ReadVarunt
binary.Varint
For example:
f, _ := os.Open(filePath)
b1 := make([]byte, 2)
_, _ = f.Read(b1)
buf := bytes.NewReader(b1)
var i int16
_ = binary.Read(buf, binary.BigEndian, &i)
fmt.Printf("Int: %s\n", string(i))
f.Close()And it always just prints weird symbols or blanks when outputting using fmt.Printf
For comparison, in JavaScript I would create a DataView on my file and then just use methods like getInt16() and it works fine.
In Python 3 I would use int.from_bytes(bytes_list, byteorder='big')
So what am I missing?
I agree with Brainstorm's approach: assuming that you're passing a machine-friendly binary representation, use the encoding/binary library. The OP suggests that binary.Write() might have some overhead. Looking at the source for the implementation of Write(), I see that it does some runtime decisions for maximum flexibility.
func Write(w io.Writer, order ByteOrder, data interface{}) error {
// Fast path for basic types.
var b [8]byte
var bs []byte
switch v := data.(type) {
case *int8:
bs = b[:1]
b[0] = byte(*v)
case int8:
bs = b[:1]
b[0] = byte(v)
case *uint8:
bs = b[:1]
b[0] = *v
...
Right? Write() takes in a very generic data third argument, and that's imposing some overhead as the Go runtime then is forced into encoding type information. Since Write() is doing some runtime decisions here that you simply don't need in your situation, maybe you can just directly call the encoding functions and see if it performs better.
Something like this:
package main
import (
"encoding/binary"
"fmt"
)
func main() {
bs := make([]byte, 4)
binary.LittleEndian.PutUint32(bs, 31415926)
fmt.Println(bs)
}
Let us know how this performs.
Otherwise, if you're just trying to get an ASCII representation of the integer, you can get the string representation (probably with strconv.Itoa) and cast that string to the []byte type.
package main
import (
"fmt"
"strconv"
)
func main() {
bs := []byte(strconv.Itoa(31415926))
fmt.Println(bs)
}
Check out the "encoding/binary" package. Particularly the Read and Write functions:
binary.Write(a, binary.LittleEndian, myInt)
Hi,I am trying to rewrite some python lines to golang and I am stuck on converting byte array to int (little-endian byteorder)
python:
bytes1 = [84, 48, 92]bytes2 = [84, 48, 92, 91, 244]num1 = int.from_bytes(bytes1, "little")print(f"num1: ", num1)num2 = int.from_bytes(bytes2, "little")print(f"num2: ", num2)
gives me output:
num1: 6041684
num2: 1049504788564
and in golang :
`bytes1 := []byte{84, 48, 92}`
`bytes2 := []byte{84, 48, 92, 91, 244}`
`num1 := int(binary.LittleEndian.Uint16(bytes1))`
`fmt.Println("num1:", num1)`
`num2 := int(binary.LittleEndian.Uint32(bytes2))`
`fmt.Println("num2:", num2)`
I get:
num1: 12372
num2: 1532768340
can someone tell me what am I doing wrong ?
I'm reading bytes from a file (image pixel data) and need to parse integers. Currently doing it with an io.Reader on the file and it works fine, but I also want to be able to parse []byte directly.
int8, uint8, int16, and uint16 are easy but I'm having trouble parsing int32 and uint32.
For example, I have this byte array: [56 66 73 77]
The parsed int32 should be 334244, big endian.
Using the aforementioned io.Reader works:
r := bufio.NewReader(file) var num int32 binary.Read(r, binary.BigEndian, &num )
But converting the bytes directly doesn't work, it yields 943868237 instead of the expected 334244
int32(binary.BigEndian.Uint32(bytes))
Same with this method:
int32(b[3]) + (int32(b[2]) << 8) + (int32(b[1]) << 16) + (int32(b[0]) << 24)
Same with using a Reader on the bytes slice:
r := bytes.NewReader(bytes) var num int32 binary.Read(1, binary.BigEndian, &num)
I'm used to working in higher level languages like Python and JavaScript so I might be missing something obvious. Any help is much appreciated.
var ba = []byte{ 56, 66, 73, 77 }
var value int32
value |= int32(ba[0])
value |= int32(ba[1]) << 8
value |= int32(ba[2]) << 16
value |= int32(ba[3]) << 24
reverse the indexing order to switch between big and little endian.
For example, I have this byte array: [56 66 73 77]
The parsed int32 should be 334244, big endian.
I don't think it should, int32(334244) is [0 5 25 164] in big endian:
https://play.golang.org/p/ElhI_n4Kbe
You can just convert an int to a byte: https://play.golang.org/p/w0uBGiYOKP
val := "7"
i, _ := strconv.Atoi(val)
byteI := byte(i)
fmt.Printf("%v (%T)", byteI, byteI)
compiler complains that i can't do i.(byte)
Of course, because that is a type assertion, it will fail if i is not of the given type (byte in your example) or it's not an interface.
In order to use a type assertion (which you're doing), you need to have an interface on the left. You're likely receiving an error along the lines of "non-interface type byte on left"-- which is true, because you already know the type. Instead, you should be casting.
You'll want to use byte(i) instead of i.(byte):
i := 12
c := byte(i)
fmt.Println(c) //12
Be careful when you have an int that exceeds the max int a byte can hold; you will end up overflowing the byte. In this case, if it's over 255 (the most a single byte can hold), you'll overflow.
numMsgByte is not a byte, it is a []byte, which contains 5 (not "5"). When you convert it to string using string(numMsgByte), you get a string "\x5".
What you need is: int(numMsgType[0])
The correct way to get an integer out of Redis using redigo would be to just use redis.Int in the first place, instead of using redis.Bytes and trying to convert the result to an int yourself.
In general though, to convert an arbitrary byte array to the integer it represents, you would use the encoding/binary package. You'll need to know some key details about the byte array though:
- Does it represent a signed or unsigned value?
- Of what width? 32 bit? 64 bit?
- Of what byte order? Big-endian? Little-endian?
- Are you sure it's represented as an integer, not e.g. a float, or a string representation of a number?
To quote the example from the docs:
b := []byte{0xe8, 0x03, 0xd0, 0x07}
x1 := binary.LittleEndian.Uint16(b[0:])
x2 := binary.LittleEndian.Uint16(b[2:])
fmt.Printf("%#04x %#04x\n", x1, x2)
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
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]))
}
You want Int.SetBytes to make a big.int from a slice of []byte.
func (z *Int) SetBytes(buf []byte) *Int
SetBytes interprets buf as the bytes of a big-endian unsigned integer, sets z to that value, and returns z.
This should be quite straightforward to use in your application since your keys are in big-endian format according to the doc you linked.
import "math/big"
z := new(big.Int)
z.SetBytes(byteSliceHere)