Golang append()

Go 的 slice 可以看成一個帶有一些資訊及指向底層 array 指標的 struct。append() 會依照底層 array 擁有的空間以及空間擴張演算法決定是否 allocate 一塊新的 array 來當底層 array。

以下用兩個例子顯示有時候 append() 會 allocate 新的底層 array,有時不會。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main() {
x := make([]int, 5)

fmt.Println("x =", x)
fmt.Println("---")

y := append(x, 3)
fmt.Println("x =", x)
fmt.Println("y =", y)
fmt.Println("---")

x[0] = 123
fmt.Println("x =", x)
fmt.Println("y =", y)
}

執行結果:

1
2
3
4
5
6
7
x = [0 0 0 0 0]
---
x = [0 0 0 0 0]
y = [0 0 0 0 0 3]
---
x = [123 0 0 0 0]
y = [0 0 0 0 0 3]

這個例子可以看到 append 後的 y 底層的 array 已經跟 x 底層的 array 不同。

再來看看底層 array 相同的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
x := make([]int, 5)
x = x[:3]

fmt.Println("x =", x)
fmt.Println("---")

y := append(x, 3)
fmt.Println("x =", x)
fmt.Println("y =", y)
fmt.Println("---")

x[0] = 123
fmt.Println("x =", x)
fmt.Println("y =", y)
}

執行結果:

1
2
3
4
5
6
7
x = [0 0 0]
---
x = [0 0 0]
y = [0 0 0 3]
---
x = [123 0 0]
y = [123 0 0 3]

從結果可以看到,當把 x[0] 設為 123 時 y[0] 也變成 123,表示 xy 的底層 array 是相同的。

我們不知道 append() 操作後,是否會重新分配 array。因此不能假設 append() 操作後產生的 slice 跟原本的 slice 是同一個,通常會寫成:

1
nums = append(nums, x)