Slice 的四種建立方式與 nil

選哪一種取決於兩件事:內容知不知道之後要用 index 指派還是用 append

// 一、已知內容:直接用字面量
people := []string{"Aaron", "Jim", "Bob", "Ken"}
 
// 二、make 給 len:開好位置填 zero value,之後用 index 指派
scores := make([]int, 4)          // len=4 cap=4  [0 0 0 0]
 
// 三、只宣告不配置:搭配 append
var names []string                // len=0 cap=0  nil
 
// 四、make 給 len=0 加 cap:大概知道要幾個,搭配 append
buf := make([]string, 0, 5)       // len=0 cap=5  []

make 的三種給法

make([]T, len, cap) 的第三個參數可省略,省略時 cap 等於 len:

寫法lencap之後怎麼填
make([]int, 4)44s[i] = x(位置已存在)
make([]int, 0, 5)05s = append(s, x)(不會觸發擴容)
make([]int, 4, 10)410前 4 個用 index,之後 append

選錯的後果是實際的:make([]int, 0, 10) 之後寫 s[7] = 9 會 panic(len 不夠),而 make([]int, 10) 之後 append 會從第 11 個開始接,前面多出 10 個 0。

nil 是 slice 的 zero value

var s []int 得到的 slice 是 nil:len 與 cap 都是 0,而且沒有底層 array(連空的都沒有)。

var s []int
fmt.Println(len(s), cap(s), s == nil)   // 0 0 true
s = append(s, 1)                        // 可以直接 append,會替它配置

實用上 nil slice 幾乎等同空 slice:len()rangeappend 都能直接用,不需要先初始化。差別只在 s == nil 的判斷,以及序列化成 JSON 時 nil 變 null、空 slice 變 []

相關:Slice 是看向底層 array 的一扇窗戶append 的行為取決於 cap 夠不夠