go - 如何将 int 数组快速转换为字节数组?
问题描述
int16
我有一个过程需要每隔几毫秒将大量 s 打包到 protobuf 中。了解它的 protobuf 方面并不重要,因为我真正需要的是将一堆int16
s(其中 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 数据结构,因为我在完全不相关的代码部分中遇到了崩溃。
解决方案
上述代码的更快版本是:
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