我从 UDP 套接字获得一个字节切片 ( []byte
),并希望将其视为一个整数切片 ( []int32
),而不更改底层数组,反之亦然。在 C(++) 中,我只是在指针类型之间转换;我将如何在 Go 中执行此操作?
原文由 slartibartfast 发布,翻译遵循 CC BY-SA 4.0 许可协议
我从 UDP 套接字获得一个字节切片 ( []byte
),并希望将其视为一个整数切片 ( []int32
),而不更改底层数组,反之亦然。在 C(++) 中,我只是在指针类型之间转换;我将如何在 Go 中执行此操作?
原文由 slartibartfast 发布,翻译遵循 CC BY-SA 4.0 许可协议
你可以做你在 C 中做的事情,但有一个例外——Go 不允许从一种指针类型转换为另一种指针类型。嗯,确实如此,但是你必须使用 unsafe.Pointer 来告诉编译器你知道所有规则都被破坏了并且你知道你在做什么。这是一个例子:
package main
import (
"fmt"
"unsafe"
)
func main() {
b := []byte{1, 0, 0, 0, 2, 0, 0, 0}
// step by step
pb := &b[0] // to pointer to the first byte of b
up := unsafe.Pointer(pb) // to *special* unsafe.Pointer, it can be converted to any pointer
pi := (*[2]uint32)(up) // to pointer to the first uint32 of array of 2 uint32s
i := (*pi)[:] // creates slice to our array of 2 uint32s (optional step)
fmt.Printf("b=%v i=%v\n", b, i)
// all in one go
p := (*[2]uint32)(unsafe.Pointer(&b[0]))
fmt.Printf("b=%v p=%v\n", b, p)
}
显然,你应该小心使用“不安全”包,因为 Go 编译器不再牵着你的手 - 例如,你可以在这里写 pi := (*[3]uint32)(up)
编译器不会抱怨,但你会遇到麻烦.
此外,正如其他人已经指出的那样,uint32 的字节在不同计算机上的布局可能不同,因此您不应假设这些是您需要的布局。
所以最安全的方法是一个一个地读取你的字节数组,并从中获取你需要的任何东西。
亚历克斯
原文由 alex 发布,翻译遵循 CC BY-SA 3.0 许可协议
7 回答5.3k 阅读
6 回答6.8k 阅读✓ 已解决
4 回答2.3k 阅读
1 回答3.4k 阅读
2 回答935 阅读✓ 已解决
2 回答2.3k 阅读
1 回答2.2k 阅读
正如其他人所说,投射指针在 Go 中被认为是不好的形式。以下是正确的 Go 方式和 C 数组转换的等效方式的示例。
警告:所有代码未经测试。
正确的方式
在此示例中,我们使用
encoding/binary
包将每组 4 个字节转换为int32
。这更好,因为我们指定了字节顺序。我们也没有使用unsafe
包来破坏类型系统。错误的方式(C 数组转换)
在这个例子中,我们告诉 Go 忽略类型系统。这不是一个好主意,因为它可能在 Go 的另一个实现中失败。它假设语言规范中没有的东西。然而,这个并没有做完整的复制。此代码使用不安全访问所有切片中通用的“SliceHeader”。标头包含指向数据(C 数组)、长度和容量的指针。我们首先需要更改长度和容量,而不是仅仅将标头转换为新的切片类型,因为如果我们将字节视为新类型,则元素会更少。