如何将int数组快速转换为字节数组?

时间:2019-04-18 22:50:42

标签: go type-conversion memcpy

我有一个过程,需要每隔几毫秒将一大堆int16打包到一个protobuf中。理解protobuf的一面并不重要,因为我真正需要的只是将一堆int16(其中160-16k)转换为[]byte的方法。这是对CPU至关重要的操作,所以我不想做这样的事情:

for _, sample := range listOfIntegers {
  protobufObject.ByteStream = append(protobufObject.Bytestream, byte(sample>>8))
  protobufObject.ByteStream = append(protobufObject.Bytestream, byte(sample&0xff))
}

(如果您感兴趣,这就是protobuf)

message ProtobufObject {
  bytes byte_stream = 1;
  ...               = 2;
  etc.
}

必须有一种更快的方法来将整数列表作为内存块提供给protobuf。我一直在摆弄cgo库以获取对memcpy的访问权,但是怀疑我一直在破坏底层的go数据结构,因为我在完全不相关的代码部分中崩溃了。

1 个答案:

答案 0 :(得分:1)

上述代码的更快版本是:

protobufObject.ByteStream := make([]byte, len(listOfIntegers) * 2)
for i, n := range listOfIntegers {
  j := i * 2
  protobufObject.ByteStream[j+1] = byte(n)
  protobufObject.ByteStream[j] = byte(n>>8)
}

在大端架构上运行时,可以避免复制数据。

使用unsafe包将[]int16标头复制到[]byte标头。再次使用不安全的程序包获取指向[]byte header的指针,并调整转换的长度和容量。

b = *(*[]byte)(unsafe.Pointer(&listOfIntegers))
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
hdr.Len *= 2
hdr.Cap *= 2
protobufObject.ByteStream = b