例如:我想使用反射来获取切片的数据作为操作它的数组。
func inject(data []int) {
sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
dh := (*[len(data)]int)(unsafe.Pointer(sh.Data))
printf("%v\n", dh)
}
由于len(data)
不是常数,此函数将产生编译错误。我该如何解决?
答案 0 :(得分:4)
要添加到@icza的注释中,您可以使用&data[0]
轻松提取基础数组-假设data
是初始化的切片。哎呀,这里没有必要跳过障碍:第一个slice的元素的地址实际上是slice的基础数组中第一个插槽的地址-在这里没有魔术。
由于创建数组元素的地址而创建 对内存的引用-只要垃圾回收器是 有关-您可以放心地让切片本身超出范围 而不必担心该阵列的内存无法访问。
唯一无法真正完成结果的事情 指针传递取消引用的结果。 这仅仅是因为Go中的数组的长度被编码为 它们的类型,因此您将无法创建一个函数来接受 这样的数组-因为您事先不知道数组的长度。
现在请停下来思考。
从切片中提取支持数组后, 指向数组内存的指针。 要明智地随身携带,您还需要随身携带 数组的长度……但这正是切片的作用: 他们将支持数组的地址与 数据(还有容量)。
因此,我真的认为您应该重新考虑您的问题 从我的立场来看,我倾向于认为这不是问题 首先。
在 种情况下,使用指向后备数组的指针
从切片中提取可能会有所帮助:例如,在“合并”时
这样的数组(例如,通过sync.Pool
)以减少内存流失
在某些情况下,但这是具体问题。
如果您有具体问题,请说明它
不是您尝试的解决方案-@Flimzy说了什么。
更新,我认为我应该更好地解释
您无法真正处理结果 指针绕过取消引用它的结果。
位。
关于Go中数组(与切片相反)的关键点 是数组(就像Go中的所有内容)都被传递了 按值,对于数组,这意味着将复制其数据。
也就是说,如果有
var a, b [8 * 1024 * 1024]byte
...
b = a
语句b = a
实际上将复制8 MiB数据。
函数参数显然也是如此。
切片通过握住指针避开了此问题
到基础(支持)数组。所以分片价值
有点struct
类型,包含
一个指针和两个整数。
因此,复制它确实很便宜,但可以“交换”它
具有参考语义:原始值和
它的副本指向相同的后备数组-即,
引用相同的数据。
我真的建议您阅读这两篇文章, 按照指示的顺序: