好吧,我找到了一个总的解决方案。显然,切片的结构包含指向后备字节数组的指针、后备字节数组的长度以及后备字节数组的容量。
我只对指向字节数组的指针感兴趣,所以我只需要切片内部数据的第一个成员。
Gounsafe.Pointer
不会将切片转换为不安全指针,但会将指向切片的指针转换为不安全指针。因为我可以将一个不安全的指针转换为我想要的任何旧类型的指针,所以我可以将它转换为一个指向指针的指针,它恢复切片内部数据的第一个成员。
这是一个工作示例。我想要一个uintptr
,但你可以将它转换为任何指针类型。
package main
import (
"fmt"
"unsafe"
)
func main() {
// Arbitrary size
n := 4
// Create a slice of the correct size
m := make([]int, n)
// Use convoluted indirection to cast the first few bytes of the slice
// to an unsafe uintptr
mPtr := *(*uintptr)(unsafe.Pointer(&m))
// Check it worked
m[0] = 987
// (we have to recast the uintptr to a *int to examine it)
fmt.Println(m[0], *(*int)(unsafe.Pointer(mPtr)))
}
如果你想要一个*int
,你可以做mPtr := *(**int)(unsafe.Pointer(&m))
只要一个切片维护这个内部数据结构,它就可以工作。我绝对愿意接受一个不依赖于 Go 内部结构的更强大的解决方案。