自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go 中切片(Slice)的長(zhǎng)度與容量

開(kāi)發(fā) 后端
在 Go 中,切片長(zhǎng)度 是切片中可用元素的數(shù)量,而 切片容量 是后臺(tái)數(shù)組中的元素?cái)?shù)量。

切片長(zhǎng)度與容量在 Go 中很常見(jiàn)。切片長(zhǎng)度是切片中可用元素的數(shù)量,而切片容量是從切片中第一個(gè)元素開(kāi)始計(jì)算的底層數(shù)組中的元素?cái)?shù)量。

Go 中的開(kāi)發(fā)者經(jīng)常混淆切片長(zhǎng)度和容量,或者對(duì)它們不夠了解。理解這兩個(gè)概念對(duì)于高效處理切片的核心操作,比如切片的初始化、使用 append 添加元素、復(fù)制或切片操作等,至關(guān)重要。對(duì)這些概念的誤解可能導(dǎo)致切片的不合理使用,甚至造成內(nèi)存泄漏。

在 Go 中,切片是由數(shù)組支持的。這意味著切片的數(shù)據(jù)以連續(xù)的方式存儲(chǔ)在數(shù)組數(shù)據(jù)結(jié)構(gòu)中。切片還負(fù)責(zé)在底層數(shù)組已滿(mǎn)時(shí)添加元素,或在幾乎為空時(shí)縮減底層數(shù)組。

在內(nèi)部,切片包含指向底層數(shù)組的指針,以及長(zhǎng)度和容量。長(zhǎng)度表示切片包含的元素?cái)?shù)量,而容量表示底層數(shù)組中的元素?cái)?shù)量,從切片中的第一個(gè)元素開(kāi)始計(jì)算。讓我們通過(guò)一些示例來(lái)更清楚地了解這些概念。首先,讓我們使用給定的長(zhǎng)度和容量初始化一個(gè)切片:

s := make([]int, 3, 6) // Three-length, six-capacity slice

第一個(gè)參數(shù),表示長(zhǎng)度,是必須的。但是,第二個(gè)參數(shù)表示容量是可選的。圖1展示了此代碼在內(nèi)存中的結(jié)果。

Figure 1 — 一個(gè)長(zhǎng)度為3、容量為6的切片

在這種情況下,make 創(chuàng)建了一個(gè)包含六個(gè)元素的數(shù)組(容量)。但由于長(zhǎng)度設(shè)置為3,Go 只初始化了前三個(gè)元素。另外,因?yàn)榍衅?nbsp;[]int 類(lèi)型,所以前三個(gè)元素被初始化為 int 類(lèi)型的零值:0?;疑匾呀?jīng)分配但尚未使用。

如果我們打印這個(gè)切片,會(huì)得到長(zhǎng)度范圍內(nèi)的元素 [0 0 0]。如果我們將 s[1] 設(shè)為1,切片的第二個(gè)元素會(huì)更新,但不會(huì)影響其長(zhǎng)度或容量。圖2說(shuō)明了這一點(diǎn)。

圖2 — 更新切片的第二個(gè)元素:s[1] = 1

然而,訪問(wèn)超出長(zhǎng)度范圍之外的元素是被禁止的,即使它在內(nèi)存中已經(jīng)分配。例如,s[4] = 0 會(huì)導(dǎo)致以下 panic:

panic: runtime error: index out of range [4] with length 3

我們?nèi)绾问褂们衅S嗟目臻g呢?通過(guò)使用內(nèi)置函數(shù) append:

s = append(s, 2)

這段代碼向現(xiàn)有的 s 切片追加了一個(gè)新元素。它使用了第一個(gè)灰色元素(已分配但尚未使用)來(lái)存儲(chǔ)元素2,正如圖3所示。

圖3 — 向 s 切片追加一個(gè)元素

切片的長(zhǎng)度從3更新為4,因?yàn)楝F(xiàn)在切片包含了四個(gè)元素?,F(xiàn)在,如果我們?cè)偬砑尤齻€(gè)元素以至于后臺(tái)數(shù)組不夠大,會(huì)發(fā)生什么?

s = append(s, 3, 4, 5)
fmt.Println(s)

如果我們運(yùn)行這段代碼,會(huì)看到切片能夠滿(mǎn)足我們的請(qǐng)求:

[0 1 0 2 3 4 5]

因?yàn)閿?shù)組是一個(gè)固定大小的結(jié)構(gòu),在第4個(gè)元素之前,它能夠存儲(chǔ)新的元素。當(dāng)我們想要插入第5個(gè)元素時(shí),數(shù)組已經(jīng)滿(mǎn)了:Go 內(nèi)部會(huì)創(chuàng)建另一個(gè)數(shù)組,將所有元素復(fù)制過(guò)去,然后再插入第5個(gè)元素。圖4展示了這個(gè)過(guò)程。

圖4 — 因?yàn)槌跏嫉暮笈_(tái)數(shù)組已滿(mǎn),Go 創(chuàng)建了另一個(gè)數(shù)組并復(fù)制了所有元素。

現(xiàn)在切片引用了新的后臺(tái)數(shù)組。之前的后臺(tái)數(shù)組會(huì)怎樣呢?如果它不再被引用,它最終會(huì)被垃圾收集器(GC)釋放,如果它是在堆上分配的話(我們?cè)阱e(cuò)誤#95 “不理解堆棧與堆的區(qū)別”中討論了堆內(nèi)存,并在錯(cuò)誤#99 “不理解GC的工作原理”中討論了GC的工作原理)。

對(duì)切片進(jìn)行切片操作會(huì)發(fā)生什么?切片是對(duì)數(shù)組或切片進(jìn)行的操作,提供了一個(gè)左閉右開(kāi)的范圍;第一個(gè)索引是包括的,而第二個(gè)索引是排除的。以下示例展示了影響,并在圖5中顯示了內(nèi)存中的結(jié)果:

s1 := make([]int, 3, 6) // Three-length, six-capacity slice
s2 := s1[1:3] // Slicing from indices 1 to 3

圖5 — 切片 s1 和 s2 引用相同的后臺(tái)數(shù)組,但長(zhǎng)度和容量不同

首先,s1 是一個(gè)長(zhǎng)度為3、容量為6的切片。當(dāng)通過(guò)對(duì) s1 進(jìn)行切片創(chuàng)建 s2 時(shí),兩個(gè)切片都引用同一個(gè)后臺(tái)數(shù)組。但是,s2 從不同的索引開(kāi)始,即索引1。因此,它的長(zhǎng)度和容量(長(zhǎng)度為2,容量為5)與 s1 不同。如果我們更新 s1[1] 或 s2[0],則更改會(huì)作用于同一個(gè)數(shù)組,因此在兩個(gè)切片中都是可見(jiàn)的,如圖6所示。

圖6 — 因?yàn)?s1 和 s2 共享同一個(gè)數(shù)組,更新共同的元素會(huì)使兩個(gè)切片中的更改都可見(jiàn)

現(xiàn)在,如果我們向 s2 添加一個(gè)元素會(huì)發(fā)生什么?以下代碼會(huì)同時(shí)改變 s1 嗎?

s2 = append(s2, 2)

共享的后臺(tái)數(shù)組被修改,但只有 s2 的長(zhǎng)度發(fā)生了變化。圖7展示了向 s2 添加元素的結(jié)果。

圖7 — 向 s2 添加元素

s1 仍然是一個(gè)長(zhǎng)度為3、容量為6的切片。因此,如果我們打印 s1 和 s2,添加的元素只會(huì)在 s2 中可見(jiàn):

s1=[0 1 0], s2=[1 0 2]

很重要理解這種行為,這樣我們?cè)谑褂?nbsp;append 時(shí)就不會(huì)形成錯(cuò)誤的假設(shè)。

注意: 在這些示例中,后臺(tái)數(shù)組是內(nèi)部的,不直接對(duì) Go 開(kāi)發(fā)者可見(jiàn)。唯一的例外是從現(xiàn)有數(shù)組切片創(chuàng)建切片。

還有最后一件事需要注意:如果我們不斷向 s2 中添加元素,直到后臺(tái)數(shù)組滿(mǎn)為止,內(nèi)存狀態(tài)會(huì)是怎樣的?讓我們?cè)偬砑尤齻€(gè)元素,以便后臺(tái)數(shù)組沒(méi)有足夠的容量:

s2 = append(s2, 3)
s2 = append(s2, 4) // At this stage, the backing is already full
s2 = append(s2, 5)

這段代碼導(dǎo)致創(chuàng)建了另一個(gè)后臺(tái)數(shù)組。圖 8 展示了內(nèi)存中的結(jié)果。

圖 8 — 向 s2 添加元素直到后臺(tái)數(shù)組已滿(mǎn)

s1 和 s2 現(xiàn)在引用兩個(gè)不同的數(shù)組。由于 s1 仍然是一個(gè)三長(zhǎng)度、六容量的切片,它仍然有一些可用緩沖區(qū),因此它繼續(xù)引用最初的數(shù)組。而且,新的后臺(tái)數(shù)組是通過(guò)從 s2 的第一個(gè)索引復(fù)制初始數(shù)組而生成的。這就是為什么新數(shù)組從元素 1 開(kāi)始,而不是 0。

結(jié)論

總結(jié)一下,切片長(zhǎng)度 是切片中可用元素的數(shù)量,而 切片容量 是后臺(tái)數(shù)組中的元素?cái)?shù)量。向一個(gè)已滿(mǎn)的切片(長(zhǎng)度 == 容量)添加元素會(huì)導(dǎo)致創(chuàng)建一個(gè)新的后臺(tái)數(shù)組,將之前數(shù)組中的所有元素復(fù)制到新數(shù)組中,并更新切片指向新數(shù)組。

責(zé)任編輯:趙寧寧 來(lái)源: 技術(shù)的游戲
相關(guān)推薦

2021-07-13 06:44:04

Go語(yǔ)言數(shù)組

2022-02-09 16:02:26

Go 語(yǔ)言ArraySlice

2024-01-09 16:14:39

RustGo切片

2021-10-15 08:57:40

內(nèi)存容量

2021-07-30 07:02:34

Slice數(shù)組切片

2012-06-15 09:56:40

2022-06-02 13:54:04

Go數(shù)組切片

2021-04-09 10:38:59

Go 語(yǔ)言數(shù)組與切片

2023-03-29 08:03:53

2017-08-31 11:28:47

Slice底層實(shí)現(xiàn)

2023-04-03 08:02:16

切片擴(kuò)容GO

2023-10-26 07:09:30

Golangrune字符

2018-08-20 08:15:50

編程語(yǔ)言Go語(yǔ)言切片

2023-03-13 13:36:00

Go擴(kuò)容切片

2021-07-08 23:53:44

Go語(yǔ)言拷貝

2021-05-12 08:47:54

Go數(shù)組切片

2021-05-14 08:58:18

非線性安全Go

2025-03-04 00:25:55

Go開(kāi)發(fā)者切片

2022-04-06 08:19:13

Go語(yǔ)言切片

2023-11-03 14:02:04

Go切片泛型庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)