arrays - 如何在 golang 中创建具有动态长度而不是 slice 的数组?

标签 arrays go slice

比如:我想用reflect把一个slice的数据作为一个数组来操作。

func inject(data []int) {
    sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
    dh := (*[len(data)]int)(unsafe.Pointer(sh.Data))
    printf("%v\n", dh)
}

此函数将发出编译错误,因为 len(data) 不是常量。我该如何解决?

最佳答案

添加到 @icza的注释,您可以使用 &data[0] 轻松提取底层数组——假设 data 是一个初始化的 slice 。 IOW,这里没有必要跳过箍:第一个 slice 元素的地址实际上是 slice 底层数组中第一个槽的地址——这里没有魔法。

由于获取数组元素的地址正在创建 对该内存的引用——只要垃圾收集器是 关注——你可以安全地让 slice 本身超出范围 不用担心该阵列的内存变得无法访问。

唯一你不能真正用结果做的事情 指针正在传递取消引用它的结果。 这仅仅是因为 Go 中的数组将它们的长度编码为 他们的类型,所以你将无法创建一个函数来接受 这样的数组——因为你事先不知道数组的长度。

现在请停下来想一想。

从 slice 中提取支持数组后,您有 指向数组内存的指针。 为了明智地随身携带它,您还需要随身携带 数组的长度……但这正是 slice 的作用: 他们将后备数组的地址与 其中的数据(以及容量)。

因此我真的认为你应该重新考虑你的问题 从我的立场来看,我倾向于认为这不是问题 开始。

情况下,使用指向后备数组的指针 从 slice 中提取可能有帮助:例如,当“池化” 这样的数组(比如,通过 sync.Pool)来减少内存流失 在某些情况下,但这些都是具体问题。 如果您遇到具体问题,请解释, 不是您尝试的解决方案——@Flimzy 所说的。


更新 我想我应该更好地解释

you can't really do with the resulting pointer is passing around the result of dereferencing it.

位。

关于 Go 中数组的一个关键点(相对于 slice ) 是数组——就像 Go 中的所有东西一样——被传递 按值,对于数组,这意味着它们的数据被复制。

也就是说,如果你有

var a, b [8 * 1024 * 1024]byte
...
b = a

b = a 语句实际上会复制 8 MiB 的数据。 显然这同样适用于函数的参数。

slice 通过持有指针来回避这个问题 到底层(支持)阵列。所以 slice 值 是一个小的 struct 类型,包含 一个指针和两个整数。 因此,复制它确实很便宜,但“作为交换” 具有引用语义:原始值和 它的副本指向同一个后备数组——也就是说, 引用相同的数据。

我真的建议你阅读这两篇文章, 按照指定的顺序:

  1. https://blog.golang.org/go-slices-usage-and-internals
  2. https://blog.golang.org/slices

关于arrays - 如何在 golang 中创建具有动态长度而不是 slice 的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51056652/

相关文章:

go - 如何导入 "sibling"包?

json - Golang - 零值字节数组

pointers - 修复数组替换中引用不正确的 slice

python - 用另一个数组切片 numpy 数组

c# - 对返回类型使用 ReadOnlyCollection<T> 与 List<T> 与数组

python - 为什么 'groupby(x, np.isnan)' 的行为与 'groupby(x) if key is nan' 不同?

java - 创建循环来检查数组 (java)

pointers - 将指针 slice 分配给它们实现的接口(interface) slice

python - 从一个 100x100 的 pytorch 张量获得一个 10x10 的补丁,并在边界周围环绕圆环样式

javascript - AngularJS 使用 ng-repeat 迭代多层数组