1. 程式人生 > 其它 >關於golang slice切片的一個問題

關於golang slice切片的一個問題

slice[i:j:k]其中 i 表示從 slice 的第幾個元素開始切,j 控制切片的長度(j-i),k 控制切片的容量(k-i),如果沒有給定 k,則表示切到底層陣列的最尾部。

注意: k控制切片的容量,不是說k的值是多少就是cap是多少,cap=k-i

func testCapNotEnough() {
	slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	cut := slice[1:3:3]
	fmt.Println("before slice:", slice)
	fmt.Println("before cut:", cut)
	fmt.Println("before cut's cap:", cap(cut))

	cut[0] = 9
	cut = append(cut, 99)

	fmt.Println("after slice:", slice)
	fmt.Println("after cut:", cut)
	fmt.Println("after cut's cap:", cap(cut))
}
**output:**
before slice: [1 2 3 4 5 6 7 8 9 10]
before cut: [2 3]
before cut's cap: 2
after slice: [1 9 3 4 5 6 7 8 9 10]
after cut: [9 3 99]
after cut's cap: 4

再看下面的程式碼:

func testCapEnough() {
	slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	cut := slice[1:3:4]
	fmt.Println("before slice:", slice)
	fmt.Println("before cut:", cut)
	fmt.Println("before cut's cap:", cap(cut))

	cut[0] = 9
	cut = append(cut, 99)

	fmt.Println("after slice:", slice)
	fmt.Println("after cut:", cut)
	fmt.Println("after cut's cap:", cap(cut))
}
**output:**
before slice: [1 2 3 4 5 6 7 8 9 10]
before cut: [2 3]
before cut's cap: 3
after slice: [1 9 3 99 5 6 7 8 9 10]
after cut: [9 3 99]
after cut's cap: 3

為什麼只有一個一行程式碼的差距,結果差距這麼大
cut := slice[1:3:3]
cut := slice[1:3:4]
不僅源slice結果都不一樣,cut結果也不一樣
cut := slice[1:3:3] 表示cut的容量cap=3-1,而切片從slice上也是切下[1:3]兩個元素,也就是如果這時候如果append一個元素99到cut,cut切片的容量是不夠的,只能重新開闢一片記憶體,將資料拷貝過去,然後再將新增的元素99加到末尾,所以這時候的cut和slice已經不是同一個記憶體了。這就解釋了為什麼testCapNotEnough()裡append之後,slice裡沒有99這個值,另外append之前cut的cap是2,而元素數量也是2,所以append需要需要擴容將cap翻倍,也就是2翻一倍,所以append之後cut的cap是4。

再看看testCapEnough(), cut := slice[1:3:4],從slice上也是切下[1:3]兩個元素,但是切片的時候,cut的容量cap為4-1=3,也就是說這時候cut的容量還沒有滿,還能再append一個元素,同時記憶體空間還是跟slice共用同一個,所以append一個99進去的時候,slice和cut兩個切片都會有變化。