Convert int32 array to bytes in go

I am using big.NewInt (int64 (e)). Bytes () converts int32 to an array of bytes. Is there a more elegant way to do this?

I expect AQAB to be a base64 e encoded value

http://play.golang.org/p/M46X7OpZpu

const e = 65537 func base64Encode(b []byte) string { return strings.TrimRight(base64.StdEncoding.EncodeToString(b), "=") } func main() { fmt.Printf("exp %d\n", e) b := make([]byte, 4) binary.BigEndian.PutUint32(b, e) fmt.Printf("b: BigEndian.PutUint32 %x (Bad) %s\n", b, base64Encode(b)) b2 := make([]byte, 4) binary.BigEndian.PutUint32(b2, e) for i := range b2 { if b2[i] != 0 { b2 = b2[i:] break } } fmt.Printf("b2: BigEndian.PutUint32 %x (Good) %s\n", b2, base64Encode(b2)) b4 := big.NewInt(int64(e)).Bytes() fmt.Printf("b4: big.NewInt(int64(e)).Bytes() %x (Good) %s\n", b4, base64Encode(b4)) } 

Output:

 exp 65537 b: BigEndian.PutUint32 00010001 (Bad) AAEAAQ b2: BigEndian.PutUint32 010001 (Good) AQAB b4: big.NewInt(int64(e)).Bytes() 010001 (Good) AQAB exp 1 b: BigEndian.PutUint32 00000001 (Bad) AAAAAQ b2: BigEndian.PutUint32 01 (Good) AQ b4: big.NewInt(int64(e)).Bytes() 01 (Good) AQ exp 1000000 b: BigEndian.PutUint32 000f4240 (Bad) AA9CQA b2: BigEndian.PutUint32 0f4240 (Good) D0JA b4: big.NewInt(int64(e)).Bytes() 0f4240 (Good) D0JA 

Edit:

I compared b2 and b4:

 b2 1000000000 68.1 ns/op 8 B/op 1 allocs/op b4 200000000 248 ns/op 90 B/op 3 allocs/op 

Now I will use b2 ...

+8
go
source share
1 answer

For this kind of task, I think that your first parameters should always use encoding/binary and, if that is not enough, bitwise math. However, in some cases, the overhead of copying data is too high or these secure solutions are too slow:

Until I call it elegant, you can use Go unsafe and reflect * to do this very quickly. Just remember that this does not copy data; rather, it just gives you another β€œlook” at it. And being good at risk means that you need to be very careful (see Unit Tests and Code Overview), and keep in mind that you are violating Go memory security . However, when execution speed is the dominant task and your team agrees with unsafe , unsafe can rarely be beaten.

 const BYTES_IN_INT32 = 4 func UnsafeCaseInt32ToBytes(val int32) []byte { hdr := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(&val)), Len: BYTES_IN_INT32, Cap: BYTES_IN_INT32} return *(*[]byte)(unsafe.Pointer(&hdr)) } func UnsafeCastInt32sToBytes(ints []int32) []byte { length := len(ints) * BYTES_IN_INT32 hdr := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(&ints[0])), Len: length, Cap: length} return *(*[]byte)(unsafe.Pointer(&hdr)) } 

* Note. You can use SizeOf , not a constant. I like the constant better.

Update: here are some test results:

 BenchmarkB2 20000000 88.7 ns/op BenchmarkB4 5000000 309 ns/op BenchmarkUnsafe 1000000000 2.25 ns/op 
+5
source share

All Articles