首页 >后端开发 >Golang >Go 中的append() 操作中切片行为背后的秘密是什么?

Go 中的append() 操作中切片行为背后的秘密是什么?

Barbara Streisand
Barbara Streisand原创
2024-10-23 13:45:021088浏览

What's the Mystery Behind Slice Behavior in append() Operations in Go?

揭秘切片上append()的行为

在Go中,常见的做法是遇到这样的代码:

<code class="go">func main() {
    slice := make([]int, 10, 10)
    slice[0] = 0
    slice[1] = 1

    slice1 := slice
    slice1[0] = 10000
    fmt.Println(slice)

    slice1 = append(slice1, 100)
    slice1[0] = 20000

    fmt.Println(slice)
}</code>

运行时这段代码,您会注意到一些奇怪的东西:

[10000 1 0 0 0 0 0 0 0 0]
[10000 1 0 0 0 0 0 0 0 0]

直观上,人们可能会假设 slice 和 slice1 是对同一底层数组的引用。然而,这个观察提出了一个问题:为什么切片在对 slice1 进行追加操作后保持不变?

理解切片的本质

要解开这个谜团,有必要了解 Go 中切片的基本性质。切片不是指针;而是指针。它们是数组的封装。具体来说,切片包含三个元素:

  • 指向底层数组开头的指针
  • 切片的大小
  • 切片的容量(无需重新分配的最大大小) )

将 slice1 分配给 slice 时,您正在创建一个新的切片头,该头指向与 slice 相同的底层数组。这样一来,对 slice1 所做的任何修改都会直接反映在 slice 中。

append() 的影响

现在我们来分析一下append() 对切片1。 append() 函数将切片作为参数并返回一个新切片。这个新切片可能引用也可能不引用与原始切片相同的底层数组。

在这种情况下,由于切片最初的容量等于其长度,任何超过 0 个元素的 append() 操作都需要创建一个新的、更大的数组。这正是 slice1 =append(slice1, 100) 所做的。它分配一个新数组,复制旧数组的内容,并返回一个新的切片头。

将结果切片头分配给 slice1 会替换 slice1 中的前一个切片头。这意味着 slice1 现在指向与 slice 不同的底层数组。因此,对 slice1 进行的任何后续修改都不会影响切片,反之亦然。

结论

虽然切片通常会被误认为是指针,但它们实际上是不同的值类型。这种内在差异在append()操作期间表现出来。诸如 slice1 =append(slice1, 100) 之类的赋值创建一个新的切片头,该头可能指向也可能不指向与原始切片相同的底层数组。在 Go 代码中操作切片时,记住这一点至关重要。

以上是Go 中的append() 操作中切片行为背后的秘密是什么?的详细内容。更多信息请关注PHP中文网其他相关文章!

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