之前在學習 golang 時,一直在他的 slice 有一些疑惑,就把一些重點紀錄下來,幫助自己以後翻查。在這邊先複習一下,golang 有兩種很相似的集合型態,那就是有 Array 跟 Slice,先來看看 Array。

Array

var a[5]string
a[0] = "A"
a[1] = "B"
a[2] = "C"
a[3] = "D"
a[4] = "E"
// array 只要宣告了變數即可使用,不需要做初始化

看看 Array 的示意圖

Array

Slice

var a[]int
a = make([]int,5,5)
a[0] = "A"
a[1] = "B"
a[2] = "C"
a[3] = "D"
a[4] = "E"
// slice 需要使用 make 做初始化才能開始使用

這是兩者最明顯的差別,接下來談談 Slice 內部運作的原理

首先 Slice 裡面會有三種資料型態紀錄

Slice

如果以上面 code 範例示意,他的初始化圖會像下面這樣

Slice init

那我們繼續延伸一下

s = a[2:4]
//s[0] == "C"
//s[1] == "D"
//len(s) == 2
//cap(s) == 3
s[0] = "Z"
// a[2] == "Z" 這段是拿來證明 s是參照到 a

Slice slice

Slice 切片出來的東西,都是創建一個新的Slice指向原本的Slice,所以原本的abcde slice,被切成 2-4,就會變成只有 C 跟 D, 但他的容量(cap)一開始規劃出來是 5,5-2=3,長度(len)則是 4-2=2。

Slice 有一個重點就是在於 長度(len)不可大於(cap)否則會噴錯。

Slice 陷阱

我們常常需要取用某個小段的 Slice ,但 Slice 的原理都是給出參照,以上面為例,我們可能只需要 C, D 兩值,但是用 Slice 取出來卻會造成,其他 A , B , E 都一直存活著, 比較好的作法是用 copy,要如何 copy 呢,來看個範例

copy 是 buit-in function

//做一個跟 a 長度相同的 slice 
c:=make([]string,len(a))
//這樣子 c 就是複製出來的 Slice 而不是參考指向
copy(c,s)