我认为重要的是要指出并知道如果目标切片(您附加到的切片)具有足够的容量,则附加将通过重新切片目标(重新切片到 increase)“就地”发生 其长度以便能够容纳可附加的元素)。
这意味着,如果目标是通过切片更大的数组或切片创建的,其中包含超出结果切片长度的附加元素,它们可能会被覆盖。
为了演示,请看这个例子:
a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)
x, y := a[:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))
x = append(x, y...)
fmt.Printf("x: %v\n", x)
fmt.Printf("a: %v\n", a)
输出(在Go Playground 上试试):
a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 10
x: [1 2 3 4]
a: [1 2 3 4 0 0 0 0 0 0]
我们创建了一个长度为10 的“支持”数组a。然后我们通过切片这个a数组来创建x目标切片,y切片是使用复合文字[]int{3, 4}创建的。现在,当我们将y 附加到x 时,结果是预期的[1 2 3 4],但可能令人惊讶的是,支持数组a 也发生了变化,因为x 的容量为10,这就足够了附加y 到它,所以x 被重新切片,这也将使用相同的a 支持数组,append() 将复制y 的元素到那里。
如果您想避免这种情况,您可以使用full slice expression,其格式为
a[low : high : max]
它构造一个切片并通过将其设置为max - low来控制结果切片的容量。
查看修改后的示例(唯一不同的是我们创建x是这样的:x = a[:2:2]:
a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)
x, y := a[:2:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))
x = append(x, y...)
fmt.Printf("x: %v\n", x)
fmt.Printf("a: %v\n", a)
输出(在Go Playground上试试)
a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 2
x: [1 2 3 4]
a: [1 2 0 0 0 0 0 0 0 0]
如您所见,我们得到了相同的 x 结果,但后备数组 a 没有改变,因为 x 的容量“仅”为 2(感谢完整的切片表达式 a[:2:2] )。因此,为了进行追加,分配了一个新的后备数组,可以存储x 和y 的元素,这与a 不同。