dongzhukuai8177 2013-07-09 02:35
浏览 479

在go中将int32转换为字节数组

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

I expect AQAB to be the base64 encoded value of e

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
", e)

  b := make([]byte, 4)
  binary.BigEndian.PutUint32(b, e)
  fmt.Printf("b: BigEndian.PutUint32 %x (Bad) %s
", 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
", b2, base64Encode(b2))

  b4 := big.NewInt(int64(e)).Bytes()
  fmt.Printf("b4: big.NewInt(int64(e)).Bytes() %x (Good) %s
", 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've benchmarked 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

I'll use b2 for now...

  • 写回答

1条回答 默认 最新

  • doufan1363 2013-07-09 04:03
    关注

    For this kind of task I think your first options should always be using encoding/binary and, if that is insufficient, bitwise math. However, in some cases the overhead of copying data is too large or these safe solutions are too slow:

    While I would not call it elegant you can use Go's unsafe and reflect* packages to do this very quickly. Just remember, this does not copy the data; rather, it just gives you another "view" of it. And being well- unsafe means that you need to be very careful- (hello units tests and code review) and keep in mind you are breaking Go's memory safety. However, when execution speed is the dominating concern and your team agrees unsafe is warranted, unsafe can seldom be beat.

    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 may want to use SizeOf rather than a constant. I like the constant better.

    Update: here are some benchmark results:

    BenchmarkB2     20000000     88.7  ns/op
    BenchmarkB4     5000000     309    ns/op
    BenchmarkUnsafe 1000000000    2.25 ns/op
    
    评论

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)