一尘不染

在不同类型的切片之间转换

go

[]byte从UDP套接字获取了一个字节片(),并希望将其视为整数片([]int32),而无需更改基础数组,反之亦然。在C(++)中,我只是在指针类型之间进行转换;我将如何在Go中执行此操作?


阅读 306

收藏
2020-07-02

共1个答案

一尘不染

正如其他人所说,在Go中强制转换指针被认为是错误的形式。这是正确的Go方式示例以及与C数组转换等效的示例。

警告:所有代码未经测试。

正确的方式

在此示例中,我们使用encoding/binary包将每组4个字节转换为int32。这样更好,因为我们指定了字节序。我们也没有使用unsafe包破坏类型系统。

import "encoding/binary"

const SIZEOF_INT32 = 4 // bytes

data := make([]int32, len(raw)/SIZEOF_INT32)
for i := range data {
    // assuming little endian
    data[i] = int32(binary.LittleEndian.Uint32(raw[i*SIZEOF_INT32:(i+1)*SIZEOF_INT32]))
}

错误的方式(C数组转换)

在此示例中,我们告诉Go忽略类型系统。这不是一个好主意,因为它可能会在Go的另一个实现中失败。它假定的事情不在语言规范中。但是,此版本不做完整副本。此代码使用不安全的方式访问所有切片中常见的“
SliceHeader”。标头包含指向数据(C数组),长度和容量的指针。首先,我们需要更改长度和容量,而不仅仅是将标头转换为新的slice类型,因为如果将字节视为新类型,则元素数量会减少。

import (
    "reflect"
    "unsafe"
)

const SIZEOF_INT32 = 4 // bytes

// Get the slice header
header := *(*reflect.SliceHeader)(unsafe.Pointer(&raw))

// The length and capacity of the slice are different.
header.Len /= SIZEOF_INT32
header.Cap /= SIZEOF_INT32

// Convert slice header to an []int32
data := *(*[]int32)(unsafe.Pointer(&header))
2020-07-02