Golang語言中切片的長度和容量的概念和使用
本文我們來詳細講解 Go 語言中切片(Slice)的長度(Length) 和容量(Capacity)。這是理解切片工作原理的核心概念。
核心概念
長度(Length):
- 表示切片當前實際包含的元素個數(shù)。
- 通過內(nèi)置函數(shù)
len(slice)獲取。 - 訪問切片中索引
>= len(slice)的元素會引發(fā)“索引越界”的運行時恐慌(panic)。
容量(Capacity):
- 表示切片底層數(shù)組(Underlying Array)從切片的起始位置到數(shù)組末尾的元素個數(shù)。
- 它代表了切片在不分配新內(nèi)存的情況下,可以增長的最大限度。
- 通過內(nèi)置函數(shù)
cap(slice)獲取。
底層數(shù)組(Underlying Array)
切片是一個輕量級的數(shù)據(jù)結(jié)構(gòu),它提供了對底層數(shù)組一個連續(xù)片段的引用。它包含三個組件:
- 指針:指向底層數(shù)組中切片起始位置的元素。
- 長度:切片中元素的數(shù)量。
- 容量:從切片起始位置到底層數(shù)組末尾的元素數(shù)量。
這個概念是理解長度和容量區(qū)別的關(guān)鍵。
圖示與示例
讓我們通過一個例子和圖示來理解。
// 1. 創(chuàng)建一個底層數(shù)組
arr := [5]int{10, 20, 30, 40, 50} // 數(shù)組,長度和容量固定為5
// 2. 基于數(shù)組創(chuàng)建一個切片
// slice 從 arr[1] 開始,到 arr[3] 結(jié)束 (不包括 arr[4])
slice := arr[1:4] // [20, 30, 40]
此時的內(nèi)存布局可以這樣表示:
底層數(shù)組: [10, 20, 30, 40, 50]
索引: 0 1 2 3 4
^ ^
| |
slice起始 slice結(jié)束 (不包括索引4)
slice指針指向這里
- len(slice):切片包含了 arr[1], arr[2], arr[3] 這三個元素,所以 長度為 3。
- cap(slice):切片的指針從 arr[1] 開始,底層數(shù)組的末尾是 arr[4],所以從起始位置到末尾有 arr[1], arr[2], arr[3], arr[4] 這 4個位置,因此 容量為 4。
fmt.Println(slice) // 輸出: [20 30 40] fmt.Println(len(slice)) // 輸出: 3 fmt.Println(cap(slice)) // 輸出: 4
容量是如何被使用的:append 函數(shù)
當你使用 append 函數(shù)向切片追加新元素時,Go 運行時會檢查容量是否足夠。
容量足夠時:
新元素會被直接放入底層數(shù)組切片末尾之后的空間,長度增加,容量不變。newSlice := append(slice, 60) // 追加元素 60 fmt.Println(newSlice) // 輸出: [20 30 40 60] fmt.Println(len(newSlice)) // 輸出: 4 fmt.Println(cap(newSlice)) // 輸出: 4 (容量剛好夠用,沒有分配新數(shù)組) fmt.Println(arr) // 輸出: [10 20 30 40 60] (原數(shù)組被修改了!)
容量不足時:
Go 運行時會創(chuàng)建一個新的、更大的底層數(shù)組(通常是當前容量的 2 倍,但對于較小的切片,增長策略可能不同),將原有元素復(fù)制到新數(shù)組中,然后追加新元素。此時的切片引用的是一個全新的數(shù)組,與原數(shù)組無關(guān)。newSlice2 := append(newSlice, 70, 80) // 追加兩個元素,超出當前容量4 fmt.Println(newSlice2) // 輸出: [20 30 40 60 70 80] fmt.Println(len(newSlice2)) // 輸出: 6 fmt.Println(cap(newSlice2)) // 輸出: 8 (新數(shù)組的容量,通常是舊容量的2倍) fmt.Println(arr) // 輸出: [10 20 30 40 60] (原數(shù)組未受影響)
使用make創(chuàng)建切片時指定長度和容量
你可以使用 make 函數(shù)在創(chuàng)建切片時直接指定其初始長度和容量。
語法:make([]T, length, capacity)
// 創(chuàng)建一個切片,長度為3(前3個元素被初始化為零值),容量為5 s := make([]int, 3, 5) fmt.Println(s) // 輸出: [0 0 0] fmt.Println(len(s)) // 輸出: 3 fmt.Println(cap(s)) // 輸出: 5 // 你可以安全地訪問和修改 s[0], s[1], s[2] // 你可以追加最多2個新元素(5-3=2)而不會觸發(fā)重新分配 s = append(s, 1) fmt.Println(s) // 輸出: [0 0 0 1] fmt.Println(len(s)) // 輸出: 4
如果省略容量參數(shù),則容量默認與長度相等。
s2 := make([]int, 3) // len=3, cap=3 fmt.Println(s2, len(s2), cap(s2)) // 輸出: [0 0 0] 3 3
總結(jié)與要點
| 特性 | 長度 (len) | 容量 (cap) |
|---|---|---|
| 含義 | 當前元素個數(shù) | 可增長的最大限度 |
| 函數(shù) | len(s) | cap(s) |
| 動態(tài)性 | 隨 append/slice 操作變化 | 在觸發(fā)擴容前不變 |
| 用途 | 決定可訪問的元素范圍 | 影響性能(減少內(nèi)存分配和復(fù)制) |
- 切片是引用類型。多個切片可以共享同一個底層數(shù)組。修改一個切片的元素可能會影響其他共享底層數(shù)組的切片。
- “擴容”是一個相對昂貴的操作,涉及內(nèi)存分配和數(shù)據(jù)復(fù)制。在能預(yù)估所需數(shù)據(jù)量的情況下,使用
make([]T, 0, capacity)預(yù)先分配一個足夠大的容量是提升性能的有效手段。 - 對切片進行重新切片(reslicing,如
s2 := s1[1:3])操作時,新切片會和原切片共享底層數(shù)組。新切片的長度和容量會基于新的起始索引重新計算。
理解長度和容量的區(qū)別,能幫助你更好地使用切片,寫出更高效、更可靠的 Go 代碼。
到此這篇關(guān)于Golang語言中切片的長度和容量的概念和使用的文章就介紹到這了,更多相關(guān)Golang 切片的長度和容量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Go語言實現(xiàn)Base62編碼的三種方式以及對比分析
Base62 編碼是一種在字符編碼中使用62個字符的編碼方式,在計算機科學(xué)中,,Go語言是一種靜態(tài)類型、編譯型語言,它由Google開發(fā)并開源,本文給大家介紹了Go語言實現(xiàn)Base62編碼的三種方式以及對比分析,需要的朋友可以參考下2025-05-05
一百行Golang代碼實現(xiàn)簡單并發(fā)聊天室
這篇文章主要為大家詳細介紹了一百行Golang代碼如何實現(xiàn)簡單并發(fā)聊天室,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08
go面向?qū)ο蠓绞讲僮鱆SON庫實現(xiàn)四則運算
這篇文章主要為大家介紹了go面向?qū)ο蠓绞讲僮鱆SON庫實現(xiàn)四則運算的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07

