首页  >  文章  >  后端开发  >  为什么从同一底层数组创建的切片在 Go 中追加时会表现出意外的行为?

为什么从同一底层数组创建的切片在 Go 中追加时会表现出意外的行为?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-11-04 02:15:29834浏览

Why do slices created from the same underlying array exhibit unexpected behavior when appended to in Go?

意外的切片追加行为

在 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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn