Convert an integer to a byte array

GoType Conversion

Go Problem Overview


I have a function which receives a []byte but what I have is an int, what is the best way to go about this conversion ?

err = a.Write([]byte(myInt))

I guess I could go the long way and get it into a string and put that into bytes, but it sounds ugly and I guess there are better ways to do it.

Go Solutions


Solution 1 - Go

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)
}

Solution 2 - Go

Check out the "encoding/binary" package. Particularly the Read and Write functions:

binary.Write(a, binary.LittleEndian, myInt)

Solution 3 - Go

Sorry, this might be a bit late. But I think I found a better implementation on the go docs.

buf := new(bytes.Buffer)
var num uint16 = 1234
err := binary.Write(buf, binary.LittleEndian, num)
if err != nil {
	fmt.Println("binary.Write failed:", err)
}
fmt.Printf("% x", buf.Bytes())

Solution 4 - Go

i thought int type has any method for getting int hash to bytes, but first i find math / big method for this https://golang.org/pkg/math/big/

var f int = 52452356235;          // int
var s = big.NewInt(int64(f))      // int to big Int
var b = s.Bytes()                 // big Int to bytes
// b - byte slise
var r = big.NewInt(0).SetBytes(b) // bytes to big Int
var i int = int(r.Int64())        // big Int to int

https://play.golang.org/p/VAKSGw8XNQq

However, this method uses an absolute value. If you spend 1 byte more, you can transfer the sign

func IntToBytes(i int) []byte{
	if i > 0 {
		return append(big.NewInt(int64(i)).Bytes(), byte(1))
	}
	return append(big.NewInt(int64(i)).Bytes(), byte(0))
}
func BytesToInt(b []byte) int{
	if b[len(b)-1]==0 {
		return -int(big.NewInt(0).SetBytes(b[:len(b)-1]).Int64())
	}
	return int(big.NewInt(0).SetBytes(b[:len(b)-1]).Int64())
}

https://play.golang.org/p/mR5Sp5hu4jk

or new(https://play.golang.org/p/7ZAK4QL96FO)

(The package also provides functions for fill into an existing slice)

https://golang.org/pkg/math/big/#Int.FillBytes

Solution 5 - Go

Adding this option for dealing with basic uint8 to byte[] conversion

foo := 255 // 1 - 255
ufoo := uint16(foo) 
far := []byte{0,0}
binary.LittleEndian.PutUint16(far, ufoo)
bar := int(far[0]) // back to int
fmt.Println("foo, far, bar : ",foo,far,bar)

output : foo, far, bar : 255 [255 0] 255

Solution 6 - Go

Here is another option, based on the Go source code [1]:

package main

import (
   "encoding/binary"
   "fmt"
   "math/bits"
)

func encodeUint(x uint64) []byte {
   buf := make([]byte, 8)
   binary.BigEndian.PutUint64(buf, x)
   return buf[bits.LeadingZeros64(x) >> 3:]
}

func main() {
   for x := 0; x <= 64; x += 8 {
      buf := encodeUint(1<<x-1)
      fmt.Println(buf)
   }
}

Result:

[]
[255]
[255 255]
[255 255 255]
[255 255 255 255]
[255 255 255 255 255]
[255 255 255 255 255 255]
[255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255]

Much faster than math/big:

BenchmarkBig-12         28348621                40.62 ns/op
BenchmarkBit-12         731601145                1.641 ns/op
  1. https://github.com/golang/go/blob/go1.16.5/src/encoding/gob/encode.go#L113-L117

Solution 7 - Go

Convert Integer to byte slice.

import (
	"bytes"
	"encoding/binary"
	"log"
)

func IntToBytes(num int64) []byte {
	buff := new(bytes.Buffer)
	bigOrLittleEndian := binary.BigEndian
	err := binary.Write(buff, bigOrLittleEndian, num)
	if err != nil {
		log.Panic(err)
	}

	return buff.Bytes()
}

Solution 8 - Go

Maybe the simple way is using protobuf, see the Protocol Buffer Basics: Go

define message like

message MyData {
  int32 id = 1;
}

get more in Defining your protocol format

// Write
out, err := proto.Marshal(mydata)

read more in Writing a Message

Solution 9 - Go

What's wrong with converting it to a string?

[]byte(fmt.Sprintf("%d", myint))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionvascopView Question on Stackoverflow
Solution 1 - GodyooView Answer on Stackoverflow
Solution 2 - GoBrainstormView Answer on Stackoverflow
Solution 3 - GoAgniva De SarkerView Answer on Stackoverflow
Solution 4 - GoYepView Answer on Stackoverflow
Solution 5 - Gopmg7670View Answer on Stackoverflow
Solution 6 - GoZomboView Answer on Stackoverflow
Solution 7 - GoStasVoView Answer on Stackoverflow
Solution 8 - Golikid1412View Answer on Stackoverflow
Solution 9 - GoChris GregoryView Answer on Stackoverflow