在 Go 中,将元素追加到循环内的切片可能会意外更改从同一底层数组创建的现有切片的值。
问题源于切片引用底层数组值的方式。当您追加到切片时,它可能会修改现有数组或创建一个新数组。但是,如果切片是使用 make 函数创建的,则它始终引用相同的底层数组。
考虑以下代码:
<code class="go">func create(iterations int) []int { a := make([]int, 0) for i := 0; i < iterations; i++ { a = append(a, i) } return a } func main() { sliceFromLoop() sliceFromLiteral() } func sliceFromLoop() { i := create(11) j := append(i, 100) g := append(i, 101) h := append(i, 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) } func sliceFromLiteral() { i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} j := append(i, 100) g := append(i, 101) h := append(i, 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }</code>
在 sliceFromLoop 中函数中,所有新切片 (j, g, h) 与初始切片 i 共享相同的底层数组。这意味着当我们追加到 i 时,它会修改所有其他切片的最后一个元素。
为了避免这种行为,建议在追加之前复制切片到它。 copy 函数分配一个与原始切片具有相同元素的新切片。
<code class="go">func sliceFromLoopFixed() { i := create(11) j := append([]int{}, i..., 100) g := append([]int{}, i..., 101) h := append([]int{}, i..., 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }</code>
在这种情况下,新切片 j、g 和 h 都有自己的底层数组,因此 i 的值不受影响通过附录。
以上是为什么从同一底层数组创建的切片在 Go 中追加时会表现出意外的行为?的详细内容。更多信息请关注PHP中文网其他相关文章!