[英]Converting int32 to byte array in go
我正在使用 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 ...
對於這種任務,我認為您的第一個選項應該始終使用encoding/binary
,如果這不足,則按位數學。 但是,在某些情況下,復制數據的開銷太大或者這些安全的解決方案太慢:
雖然我不會稱之為優雅,但你可以使用Go的unsafe
和reflect
*包來快速完成這項工作。 請記住,這不會復制數據; 相反,它只是給你另一個“視圖”。 並且不安全意味着你需要非常小心 - (你好單元測試和代碼審查)並記住你打破了Go的內存安全性 。 然而,當執行速度是主要關注點並且你的團隊同意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
這是最直接的(也是最短的(也是最安全的)(也許是性能最好的))方式:
buf.Bytes()
是 bytes slice 類型。
var val uint32 = 42
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, val)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
fmt.Printf("% x\n", buf.Bytes())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.