-
-
Save ecoshub/5be18dc63ac64f3792693bb94f00662f to your computer and use it in GitHub Desktop.
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 | |
} |
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.
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
I've copy-pasted the gist into the playground, it worked https://go.dev/play/p/o76zx3Z4O-k
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.
@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
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?
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.
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[:]
}
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.
Verify Github on Galxe. gid:pGf2Haut6ocx4c3U6YFF6F
gid:pGf2Haut6ocx4c3U6YFF6F
Hi @ecoshub Can I use int instead of int64? and it will be fixed bytes size?
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.
Do not use unsafe in production though.
@ecoshub : How long were the test-Strings in your BtoI tests? ππ»
not only in this part but also in production servers for 4 years π @mwat56
converte the integer to string and then converts the string to []byte don't works too?