Skip to content

Instantly share code, notes, and snippets.

@ecoshub
Last active August 23, 2024 08:31
Show Gist options
  • Select an option

  • Save ecoshub/5be18dc63ac64f3792693bb94f00662f to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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

@ecoshub

ecoshub commented Dec 1, 2021

Copy link
Copy Markdown
Author

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

humsie commented Mar 5, 2022

Copy link
Copy Markdown

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
Copy Markdown

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

@humsie

humsie commented Mar 17, 2022

Copy link
Copy Markdown

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

ecoshub commented Mar 23, 2022

Copy link
Copy Markdown
Author

@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

stopcenz commented Aug 11, 2022

Copy link
Copy Markdown

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

ecoshub commented Aug 14, 2022

Copy link
Copy Markdown
Author

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

v0nc commented Sep 8, 2022

Copy link
Copy Markdown

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

ecoshub commented Sep 11, 2022

Copy link
Copy Markdown
Author

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
Copy Markdown

Verify Github on Galxe. gid:pGf2Haut6ocx4c3U6YFF6F

@The-Lumberjack

Copy link
Copy Markdown

gid:pGf2Haut6ocx4c3U6YFF6F

@ntsd

ntsd commented Sep 13, 2022

Copy link
Copy Markdown

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

@ecoshub

ecoshub commented Sep 13, 2022

Copy link
Copy Markdown
Author

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

v0nc commented Sep 16, 2022

Copy link
Copy Markdown

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
Copy Markdown

Do not use unsafe in production though.

@mwat56

mwat56 commented Aug 5, 2024

Copy link
Copy Markdown

@ecoshub : How long were the test-Strings in your BtoI tests? πŸ‘‹πŸ»

@ecoshub

ecoshub commented Aug 8, 2024

Copy link
Copy Markdown
Author

not only in this part but also in production servers for 4 years πŸ˜„ @mwat56

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