Go 的切割上限是 cap 而不是 len
x[a:b]取的是 index a 到 b-1。容易漏掉的是:b 的上限是cap,不是len,而且索引相對於被切的那個 slice 自己的起點,不是原始 array。
s := []int{1, 2, 3, 4, 5}
newSlice := s[1:3] // [2 3] len=2 cap=4
// 4、5 還躺在同一塊 array 裡,只是看不到
nonExpandedSlice := newSlice[0:] // [2 3] 省略右邊 → 用目前的 len,不擴展
expandedSlice := newSlice[0:4] // [2 3 4 5] 4 ≤ cap,把窗戶往右拉寬
// newSlice[0:5] // runtime panic:超過 cap所以「擴展 slice」的意思是把窗戶往右拉寬,把 cap 範圍內原本看不到的元素納進 len——不是產生新資料。
省略時的預設值
| 寫法 | 意思 |
|---|---|
x[a:b] | index a 到 b-1 |
x[:b] | 左邊省略 → 從 index 0 開始 |
x[a:] | 右邊省略 → 到目前的 len(不是到 cap,所以不會擴展) |
x[:] | 全部;也是把 array 轉成 slice 的標準寫法 |
超過 cap 是 runtime panic
切過頭不是編譯期錯誤,是執行期才炸:
s := []int{1, 2, 3, 4, 5}
overSliceCap := s[:6] // panic同理,len 不足時不能用 index 賦值——make([]int, 0, 10) 之後 scores[7] = 9033 不行,得先 scores = scores[0:8] 把窗戶拉開。
從 array 切出來,cap 一路吃到結尾
arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
s1 := arr[:2] // [1 2] len=2 cap=8 ← cap 是 8 不是 2cap 永遠是「原本的 cap 減掉 low」。這條規則就是 切割出的 slice 預設 cap 吃到底,append 會寫進鄰居的地盤 的成因。