Skip to content

Instantly share code, notes, and snippets.

@ecoshub
Last active December 9, 2023 18:27
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ecoshub/5be18dc63ac64f3792693bb94f00662f to your computer and use it in GitHub Desktop.
Save ecoshub/5be18dc63ac64f3792693bb94f00662f to your computer and use it in GitHub Desktop.
golang integer to byte array and byte array to integer function
package main
import (
"fmt"
"unsafe"
)
func main(){
// integer for convert
num := int64(1354321354812)
fmt.Println("Original number:", num)
// integer to byte array
byteArr := IntToByteArray(num)
fmt.Println("Byte Array", byteArr)
// byte array to integer again
numAgain := ByteArrayToInt(byteArr)
fmt.Println("Converted number:", numAgain)
}
func IntToByteArray(num int64) []byte {
size := int(unsafe.Sizeof(num))
arr := make([]byte, size)
for i := 0 ; i < size ; i++ {
byt := *(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&num)) + uintptr(i)))
arr[i] = byt
}
return arr
}
func ByteArrayToInt(arr []byte) int64{
val := int64(0)
size := len(arr)
for i := 0 ; i < size ; i++ {
*(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&val)) + uintptr(i))) = arr[i]
}
return val
}
@guilherme-de-marchi
Copy link

converte the integer to string and then converts the string to []byte don't works too?

@ecoshub
Copy link
Author

ecoshub commented Dec 1, 2021

Hi @guilherme-de-marchi if you convert integer to string and then convert to byte array its length not will be fixed. But this way it will be always the same length ( 8 byte ). There are lot of situation that you need a fixed length byte array representation of integers.

@humsie
Copy link

humsie commented Mar 5, 2022

Came across this gist while searching for something similar, and wanted to point out this gist is wrong. The order of the bytes is reversed.
output for 22233 is [217 86 0 0 0 0 0 0] but should be [0 0 0 0 0 0 86 217]

fmt.Printf("%v\n", IntToByteArray(int64(22233)))
fmt.Printf("%v\n", big.NewInt(int64(22233)).Bytes())
fmt.Printf("%d\n", ByteArrayToInt(big.NewInt(int64(22233)).Bytes()))
// Outputs:
[217 86 0 0 0 0 0 0]
[86 217]
55638

arr[I] on Line 27 and 35 should be arr[size - 1 - i] to reverse through the byte array

With those lines fixed the output is correct:

[0 0 0 0 0 0 86 217]
[86 217]
22233

@andreapavoni
Copy link

I've copy-pasted the gist into the playground, it worked https://go.dev/play/p/o76zx3Z4O-k

@humsie
Copy link

humsie commented Mar 17, 2022

After some further searching I found out that we are both right (and wrong).
There are 2 ByteOrder apparently : LittleEndian and BigEndian (I only used BigEndian before).
https://pkg.go.dev/encoding/binary#pkg-examples

This gist does LittleEndian, and with my "fix" it does BigEndian.
So check and use what you need.

https://go.dev/play/p/jdXgbSNoZB8

@ecoshub
Copy link
Author

ecoshub commented Mar 23, 2022

@humsie Sorry for delayed response. Yes this gist is for little endian encoding :) But if you are using this for data transfer no mater which encoding you use unless you decode and encode with same algorithm

@stopcenz
Copy link

stopcenz commented Aug 11, 2022

An option without using loops is possible:

func IntToByteArray(i int64) []byte {
	var b []byte
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	sh.Len = 8
	sh.Cap = 8
	sh.Data = uintptr(unsafe.Pointer(&i))

	return b[:]
}

func ByteArrayToInt(b []byte) int64 {
	return *(*int64)(unsafe.Pointer(&b[0]))
}

Are there any disadvantages other than the need to take into account the peculiarities of the GC?

@ecoshub
Copy link
Author

ecoshub commented Aug 14, 2022

I don't know about garbage collectors behavior but your suggestion is much more memory friendly and much more faster.

"Thats the way" 😄

goos: darwin
goarch: amd64
pkg: test/stable
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Benchmark_Itob-16       83581489                14.31 ns/op            8 B/op          1 allocs/op
Benchmark_Itob_2-16     99950498                11.23 ns/op            8 B/op          1 allocs/op
Benchmark_Btoi-16       469129642                2.436 ns/op           0 B/op          0 allocs/op
Benchmark_Btoi_2-16     1000000000               0.4494 ns/op          0 B/op          0 allocs/op
PASS
ok      test/stable     5.552s

NOTE: *_2 is @stopcenz 's suggestion.

@v0nc
Copy link

v0nc commented Sep 8, 2022

I wrote this not too long ago. Also as far as I know none of the examples above are specifically little- or big endian. This depends on your CPU and could (in theory) result in a big-endian byte array. Please correct me if I'm wrong tho ^^

func ItoBSlice(i int) []byte {
	data := *(*[unsafe.Sizeof(i)]byte)(unsafe.Pointer(&i))
	return data[:]
}

@ecoshub
Copy link
Author

ecoshub commented Sep 11, 2022

Hi @pyglue. I wrote for a custom network protocol. It use same encoder and decoder functions so endianness is not a problem. Also I love your method. I am gonna add your method to same benchmark below as "*_3" later.

@The-Lumberjack
Copy link

Verify Github on Galxe. gid:pGf2Haut6ocx4c3U6YFF6F

@The-Lumberjack
Copy link

gid:pGf2Haut6ocx4c3U6YFF6F

@ntsd
Copy link

ntsd commented Sep 13, 2022

Hi @ecoshub Can I use int instead of int64? and it will be fixed bytes size?

@ecoshub
Copy link
Author

ecoshub commented Sep 13, 2022

Ofcourse!. I cant see any problem with this. But remember its a 2.5 years old snippet :)) Even I dont like this code. You can use @stopcenz or @pyglue s snippets They are much more efficent. @stopcenz snippet is already int64

https://gist.github.com/ecoshub/5be18dc63ac64f3792693bb94f00662f?permalink_comment_id=4264235#gistcomment-4264235

@v0nc
Copy link

v0nc commented Sep 16, 2022

Hi @ecoshub Can I use int instead of int64? and it will be fixed bytes size?

Int isn't really a fixed size. On a 64bit system int is an int64 while on a 32bit system it will be an int32. So depending which system you compile your code for, you will end up with a different result.

@manosriram
Copy link

Do not use unsafe in production though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment