我正在使用big.NewInt(int64(e))。Bytes()将int32转换为字节数组。 有更优雅的方式吗?
我希望AQAB是e
的base64编码值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))
}
输出:
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
编辑:
我已经对b2和b4进行了基准测试:
b2 1000000000 68.1 ns/op 8 B/op 1 allocs/op
b4 200000000 248 ns/op 90 B/op 3 allocs/op
我现在要用b2 ......
答案 0 :(得分:5)
对于这种任务,我认为你的第一个选择应该始终使用encoding/binary
,如果这不足,则按位计算。但是,在某些情况下,复制数据的开销太大或者这些安全解决方案太慢了:
虽然我不会称之为优雅,但您可以使用Go的unsafe
和reflect
*包快速完成此操作。请记住,这不会复制数据;相反,它只是给你另一个“视图”。并且不安全意味着你需要非常小心 - (你好单元测试和代码审查)并记住你正在打破Go memory safety。但是,当执行速度成为主要关注点且您的团队同意unsafe
时,unsafe
很少会被击败。
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))
}
*注意:您可能希望使用SizeOf
而不是常量。我更喜欢这个常数。
更新:以下是一些基准测试结果:
BenchmarkB2 20000000 88.7 ns/op
BenchmarkB4 5000000 309 ns/op
BenchmarkUnsafe 1000000000 2.25 ns/op