切片上追加操作的意外行为
在 Go 中,在循环迭代期间将元素追加到切片然后创建新元素时,可能会出现意外行为根据结果进行切片。此行为源于对引用进行切片的底层数组。
考虑以下代码:
<code class="go">func create(iterations int) []int { a := make([]int, 0) for i := 0; i < iterations; i++ { a = append(a, i) } return a }</code>
如果我们调用 create(11) 并将结果分配给 i,我们期望每个后续追加操作 (j :=append(i, 100)、g :=append(i, 101) 和 h :=append(i, 102)) 创建具有不同值的新切片。然而,观察到的行为是,这些新切片的最后一个元素始终为 102,无论其索引如何。
发生这种情况是因为所有追加都修改相同的底层数组。将元素附加到切片会更改长度并可能导致数组的重新分配。分配新数组时,所有先前对旧数组的引用都将变得无效。
但是,切片文字的行为符合预期,因为如果追加超出后备数组的容量,则始终会分配新数组。
惯用方法
为了确保基于现有切片创建多个新切片时的可预测行为,惯用方法是在附加元素之前复制切片:
<code class="go">func makeFromSlice(sl []int) []int { result := make([]int, len(sl)) copy(result, sl) return result }</code>
通过执行复制,我们创建一个新的支持数组,并确保对结果切片所做的更改不会影响原始切片。
以上是为什么在 Go 中附加到循环中的切片会产生意外结果?的详细内容。更多信息请关注PHP中文网其他相关文章!