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

