How to use slice capacity and length in Go

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

huangwenwei - 字裡行間 | Golang 中的數組 (array) 和切片 (slice)

中文描述約定
array: 數組
slice: 切片

來做個測試,不在機器上運行下面的代碼,請給出輸出

vals :make([]int, 5)for i:= 0; i < 5; i++ {    vals = append(vals, i)}fmt.Println(vals)

如果你猜測的結果是 [0 0 0 0 0 1 2 3 4],恭喜你答對了。
為啥麼正確答案不是 [0 1 2 3 4] 呢?
大部分像我一樣 Golang 初學者都會打錯這道測試題,在這篇文章中,我們來探討一下為什麼不是我們期望的輸出結果以及 slice 資料類型中 capacity 和 length 的用法。

Slices VS Arrays

初學時可能會把 Golang 中數組和切片的區別,但是如果習慣了使用切片,將會極大地最佳化代碼;
數組和切片有很多不同點,但在這裡我們記住它們之間最大的區別就是:固定的數組大小是數組聲明時的一部分,而切片可以有一個動態大小。那麼在實際的編碼中是如何體現的呢?例如 val a [10]int, 這個數組有一個固定的大小 10 ,卻不能改變長其度;如果我們調用 len(a),返回 10,因為長度就是數組的一部分;這就導致一個問題,如果有數組長度超過 10 的需求,你必須建立另外一個數組對象,譬如 val b [11]int, 並把數組 a 的值拷貝到數組 b
在某種情境下固定長度的數組非常使用,但是通常我們長度靈活的數組,需要一種“沒有固定大小的數組”,最直接的做法是聲明數組時給足夠大的長度,例如:

var vals [20]intfor i := 0; i < 5; i++ {    vals[i] = i * i}subsetLen := 5fmt.Println("The subset of our array has a length of:" subsetLen)// Add a new item to our arrayvals[subsetLen] = 123subsetLen++fmt.Print("The subset of our array has a length of:", subsetLen)

上面的例子中,我們聲明數組時設定了其長度為 20 ,通過一個變數我們“設定”其長度為 5 ,我們往其加了一個元素之後, subset 自增 1,數組長度就變成了 6
粗略地說,這就是切片的原理,通過設定一個值來限定數組的最大長度,在上述例子中為 20 ;同時切片還有一個值來表示數組元素的真實長度,在上述例子中為 subsetLen ;故切片中有 capacity cap 和 length len 兩個概念。切片的內部實現基於數組,但是使用方式更靈活、運行更高效。cap 限定了切片中元素個數增加的上限,通過 append 函數,我們不需關心數組底層的個數上限。

回到我們的測試題

明白了數組和切片的概念和不同點之後,我們再次解釋一下測試題。
make 函數能夠聲明一個切片,第一個參數表示類型,第二個參數表示類型的長度,第三個參數為選擇性參數,表示類型的容納上限;
make([]int, 5) 表示我們要建立一個長度為 5 的切片,切片的預設容納上限(capacity)和長度一致。但是 append 函數表示切片增加一個元素,那麼該切片的容納上限將同時增加,並在切片的末尾新增一個元素。也就是預設的切片值為 [0 0 0 0 0] 增加一個元素將會被放置在在第五個元素後面,所以運行結果如下:

vals := make([]int, 5)  fmt.Println("Capacity was:", cap(vals))  for i := 0; i < 5; i++ {    vals = append(vals, i)    fmt.Println("Capacity is now:", cap(vals))}fmt.Println(vals)// output: [0 0 0 0 0 0 1 2 3 4]

如果修改為下面的代碼,則輸出為 [0, 1, 2, 3, 4]

vals := make([]int, 5)  for i := 0; i < 5; i++ {        vals[i] = i}fmt.Println(vals)

代碼不夠簡潔,改造一下:我們把 vals 的長度設定為 0 ,容納上限為 5

vals := make([]int, 0, 5)for i := 0; i < 5; i++ {    vals.appen(i)}fmt.Println(vals)

最後,如果能知道切片的上限,建議最好給 make 函數加上第三個參數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.