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