這篇主要寫兩個主題,作為 理解 golang slice 用法及原理 系列的結尾 :
var arr1 []int // nil slice
arr2 := []int{} // empty slice
nil slice 代表的是什麼都沒有, empty slice 代表長度為 0 的 slice。
再拿寶特瓶的例子出來比喻,empty slice 代表你有一個不能裝水的寶特瓶,nil slice 代表你連寶特瓶都沒有。
在 go 的語法中 len(arr1)
和 len(arr2)
都為 0,這設計很直覺,因為兩者都沒水啊。
在大部分情況,這兩瓶不能喝水的寶特瓶,意義都是一樣的。 這代表著在大部分情況下不需要特別去判斷 slice 是 nil 還是 empty。通常只使用 len(arr1) == 0
判斷,就去創建一個 slice,或是做其他事情。
但是但是,就是會有例外。你拿著不能裝水的寶特瓶去了回收廠可以換錢,但是你雙手空空去回收場是換不到錢的,對你來說兩者都不能裝水,意義是一樣的,但是對回收廠來說完全是不同的意義。
看一個實際案例,如果使用 empty slice 和 nil slice 去 marshall 的結果是不一樣的,請看程式碼。
arr1 := []int{}
arr1M, _ := json.Marshal(arr1)
fmt.Println(string(arr1M)) // print []
var arr2 []int
arr2M, _ := json.Marshal(arr2)
fmt.Println(string(arr2M)) // print null
將 a slice 複製一份到 b
b := make([]T, len(a))
刪除第 i 個元素,注意: 這不適用於指標型態或是含有指標型態的 struct。這將會造成 a 的最後一個元素無法被 gc 回收 (memory leak)
a = append(a[:i], a[i+1:]...)
刪除第 i 個元素,適用於指標型態或是含有指標型態的 struct
copy(a[i:], a[i+1:])
a[len(a)-1] = nil // or the zero value of T
a = a[:len(a)-1]
刪除第 i 到 j - 1 個元素,注意: 這不適用於指標型態或是含有指標型態的 struct。這可能會造成 a 的最後 j - i 個元素無法被 gc 回收 (memory leak)
a = append(a[:i], a[j:]...)
刪除第 i 到 j - 1 個元素,適用於指標型態或是含有指標型態的 struct。
copy(a[i:], a[j:])
for k, n := len(a)-j+i, len(a); k < n; k++ {
a[k] = nil // or the zero value of T
}
a = a[:len(a)-j+i]
插入一個元素在第 i 和 i + 1 個元素中間
s = append(s, 0 /* use the zero value of the element type */)
copy(s[i+1:], s[i:])
s[i] = x