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 不是 2

cap 永遠是「原本的 cap 減掉 low」。這條規則就是 切割出的 slice 預設 cap 吃到底,append 會寫進鄰居的地盤 的成因。

相關:Slice 是看向底層 array 的一扇窗戶