首页 > 解决方案 > 如何将 int 数组快速转换为字节数组?

问题描述

int16我有一个过程需要每隔几毫秒将大量 s 打包到 protobuf 中。了解它的 protobuf 方面并不重要,因为我真正需要的是将一堆int16s(其中 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 数据结构,因为我在完全不相关的代码部分中遇到了崩溃。

标签: gotype-conversionmemcpy

解决方案


上述代码的更快版本是:

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头中。再次使用 unsafe 包获取指向[]byte 标头的指针并调整转换的长度和容量。

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

推荐阅读