最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言中slice類型的使用小結(jié)

 更新時(shí)間:2026年03月17日 10:05:48   作者:KeithChu  
本文主要介紹了Go語言中slice類型的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. 數(shù)組和 slice

1.1. 數(shù)組

數(shù)組是具有固定長度且擁有零個(gè)或者多個(gè)相同數(shù)據(jù)類型元素的序列。由于數(shù)組的長度固定,所以在 Go 中很少直接使用。

var arr1 [3]int              // 定義一個(gè)長度為 3,元素類型為 int 的數(shù)組,元素的值為其類型的零值
arr2 := [3]int{1, 2, 3}      // 定義一個(gè)長度為 3,元素類型為 int 的數(shù)組,并用給定的值初始化每個(gè)元素
arr3 := [...]int{4, 5, 6, 7} // 如果使用 ... 代替數(shù)組的長度,Go 會根據(jù)初始化時(shí)數(shù)組元素的數(shù)量確定數(shù)據(jù)的長度
arr4 := [5]int{1: 10, 3: 30} // 支持索引為 1、3 的元素的值,其他索引的值為其類型的零值

fmt.Println(len(arr1), arr1)
fmt.Println(len(arr2), arr2)
fmt.Println(len(arr3), arr3)
fmt.Println(len(arr4), arr4)

輸出:

3 [0 0 0]
3 [1 2 3]
4 [4 5 6 7]
5 [0 10 0 30 0]

1.2. slice

在 Go 中,slice 表示一個(gè)擁有相同類型元素的可變長度的序列,寫作 []T,其中元素的類型都是 T。

slice 的定義位于 src/runtime/slice.go

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

其中:

  • array:指向 slice 底層數(shù)組第一個(gè)元素的指針;
  • len:slice 中當(dāng)前存儲的元素個(gè)數(shù),可以用內(nèi)置函數(shù) len() 獲??;
  • cap:slice 底層數(shù)組的長度,可以用內(nèi)置函數(shù) cap() 獲取。

1.3. 數(shù)組和 slice 的區(qū)別

  1. 數(shù)組長度是固定的,使用前必須確定長度。slice 長度可變。
  2. 數(shù)組是基于連續(xù)的內(nèi)存空間存儲數(shù)據(jù)的,作為函數(shù)參數(shù)傳遞時(shí)傳遞的是數(shù)組的拷貝。slice 是一個(gè)包含指向底層數(shù)組的指針、長度和容量的結(jié)構(gòu)體。
  3. 當(dāng)兩個(gè)數(shù)組長度相同,且數(shù)組元素類型可比較時(shí),可以使用 ==!= 來比較這兩個(gè)數(shù)組;slice 只能和 nil 比較。

2. 創(chuàng)建 slice

s1 := make([]int, 5)     // 創(chuàng)建長度為 5,容量為 5(默認(rèn)容量等于長度)的 slice
s2 := make([]int, 3, 10) // 創(chuàng)建長度為 3,顯式指定容量為 10 的 slice
s3 := []int{1, 2, 3}     // 創(chuàng)建長度為 3,容量為 3 的 slice
s4 := []int{99: 1}       // 創(chuàng)建長度為 100(長度由最大索引決定),容量為 100 的 slice。索引為 99 的元素顯式初始化為 1,其他元素為類型的零值(0)

fmt.Println(len(s1), cap(s1))
fmt.Println(len(s2), cap(s2))
fmt.Println(len(s3), cap(s3))
fmt.Println(len(s4), cap(s4))

3. 向 slice 追加元素

3.1.append函數(shù)

內(nèi)置函數(shù) append 用于將元素追加到 slice 的后面,返回追加后的 slice。

s1 = append(s1, 0)       // 向 slice s1 追加元素
s2 = append(s2, 1, 2, 3) // 向 slice s2 追加多個(gè)元素
s3 = append(s3, s2...)   // 向 slice s3 追加另一個(gè) slice s2

執(zhí)行 append 函數(shù)后,可能出現(xiàn)以下兩種情況:

  • 當(dāng) slice 還有剩余容量時(shí),append 直接追加,底層數(shù)組不變;
  • 當(dāng)容量不足時(shí),append 觸發(fā) growslice,新分配一個(gè)更大的數(shù)組,并將原元素復(fù)制過去,原數(shù)組若無引用則被 GC 回收。

3.2. slice 的擴(kuò)容策略

Slice 的擴(kuò)容策略位于 src/runtime/slice.go

// growslice 為 slice 分配新的底層存儲
// 參數(shù):
//   oldPtr = 指向 slice 底層數(shù)組的指針
//   newLen = 擴(kuò)容后的長度(oldLen + num)
//   oldCap = 原始 slice 的容量
//      num = 擴(kuò)容的元素?cái)?shù)量
//       et = 元素類型
//
// 要求 newLen 大于 oldCap(即發(fā)生了 cap 變化)
func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice {
    ...
}

// nextslicecap 計(jì)算擴(kuò)容后的 slice 容量
//
// 參數(shù):
//   newLen = 擴(kuò)容后的長度
//   oldCap = 原始 slice 的容量
func nextslicecap(newLen, oldCap int) int {
    ...
}

在 Go 1.18 及之后:

  1. 如果 slice 擴(kuò)容后的元素個(gè)數(shù)大于兩倍擴(kuò)容前的容量,新容量等于擴(kuò)容后的元素個(gè)數(shù);
  2. 如果擴(kuò)容前的容量小于 256,新容量等于兩倍擴(kuò)容前的容量;
  3. 如果擴(kuò)容前的容量大于等于 256,新容量初始值等于擴(kuò)容前的容量,每次增加 25% + 192,直到值大于新長度。

在 Go 1.18 之前

  1. 如果 slice 擴(kuò)容后元素個(gè)數(shù)大于兩倍擴(kuò)容前的容量,新容量等于擴(kuò)容后元素個(gè)數(shù);
  2. 如果擴(kuò)容前的容量小于 1024,新容量等于兩倍擴(kuò)容前的容量;
  3. 如果擴(kuò)容前的容量大于等于 1024,新容量初始值等于擴(kuò)容前的容量,每次增加 25%,直到值大于新長度。

如何理解這次變動呢?比較下兩個(gè)方式的擴(kuò)容因子:

原始容量Go 1.18 之前擴(kuò)容因子Go 1.18 及之后擴(kuò)容因子
< 2562.02.0
2562.02.0
5122.01.625
10241.251.4375
20481.251.34375
40961.251.296875
超大容量1.25無限趨近 1.25

可以看到,舊方式中,舊容量從 1024 開始擴(kuò)容因子突降至 1.25;新方式中,舊容量從 256 開始,擴(kuò)容因子平滑過渡到 1.25。

3.3. 當(dāng) slice 作為函數(shù)參數(shù)

當(dāng) slice 作為函數(shù)參數(shù)傳遞時(shí),如果需要函數(shù)內(nèi)修改 slice 的長度并對外部生效,通常應(yīng)返回新的 slice,而不是傳遞 slice 的指針 *[]int(雖然也可行,但不符合習(xí)慣)。

當(dāng)我們將 slice 作為函數(shù)參數(shù)傳遞時(shí),實(shí)質(zhì)上傳遞的是一個(gè)指向底層數(shù)組的指針、元素的個(gè)數(shù)(len)和底層數(shù)組的長度(cap)。函數(shù)內(nèi)部對 len 和 cap 的修改在函數(shù)外部不會生效,而函數(shù)內(nèi)部對 slice 元素的修改則需要分情況討論。

如果在函數(shù)內(nèi)部只修改了 slice 元素的值,在函數(shù)外部這些修改也會生效;如果在函數(shù)內(nèi)部對 slice 進(jìn)行了元素追加(修改了 len),則分為以下兩種情況:

  1. 追加元素后 slice 的 cap 沒有改變。此時(shí)函數(shù)外部 slice 和函數(shù)內(nèi)部 slice 指向的底層數(shù)組一致,所以函數(shù)內(nèi)部的修改在函數(shù)外部也是生效的。但是函數(shù)外部 slice 的 len 沒有改變,因此看不到使用 append 函數(shù)追加的元素內(nèi)容。但函數(shù)內(nèi)部對追加元素前長度范圍內(nèi)元素的修改會影響到函數(shù)外。
  2. 追加元素后 slice 的 cap 發(fā)生了改變。此時(shí) append 操作會重新創(chuàng)建一個(gè)新的底層數(shù)組,這種情況下函數(shù)內(nèi)外的 slice 指向的底層數(shù)組不一樣,對函數(shù)內(nèi) slice 的修改完全不影響函數(shù)外的 slice。

如果函數(shù)內(nèi)部需要改變原 slice 的長度或容量,并需要在函數(shù)外部生效,可以選擇返回一個(gè)新的 slice 讓函數(shù)外部接收。

4. 拷貝 slice

直接將一個(gè) slice 賦值給另一個(gè) slice,屬于淺拷貝,兩個(gè) slice 還是使用同一個(gè)底層數(shù)組。如果需要深拷貝,可以使用 copy 函數(shù)或 append 函數(shù)。

使用 copy 函數(shù):

s1 := []int{1, 2, 3}
s2 := make([]int, len(s1)) // 需要提前分配長度。如果 s2 的長度不足,則只拷貝 len(s2) 個(gè)元素
n := copy(s2, s1)          // 返回拷貝的元素?cái)?shù)量,也就是 len(src) 和 len(dst) 的最小值

使用 append 函數(shù):

s1 := []int{1, 2, 3}
s2 := append([]int(nil), s1...)

copy 效率較高,適合已有目標(biāo)切片或需要精確控制要拷貝的元素?cái)?shù)量時(shí)使用。append 寫法簡潔,適合一步完成創(chuàng)建和拷貝(但可能因擴(kuò)容機(jī)制而分配比所需更大的容量)。

到此這篇關(guān)于Go語言中slice類型的使用小結(jié)的文章就介紹到這了,更多相關(guān)Go語言 slice類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • Go語言字符串拼接方式與性能比較分析

    Go語言字符串拼接方式與性能比較分析

    這篇文章主要為大家介紹了Go語言字符串拼接方式與性能比較示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go時(shí)間操作常用方法(推薦!)

    Go時(shí)間操作常用方法(推薦!)

    平時(shí)開發(fā)過程中,時(shí)間相關(guān)的操作用的還是很多的,下面這篇文章主要給大家介紹了關(guān)于Go時(shí)間操作常用方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • golang jwt鑒權(quán)的實(shí)現(xiàn)流程

    golang jwt鑒權(quán)的實(shí)現(xiàn)流程

    本文主要介紹了golang jwt鑒權(quán)的實(shí)現(xiàn)流程,包含生成JWT令牌、客戶端存儲和發(fā)送JWT令牌、服務(wù)端驗(yàn)證JWT令牌等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02
  • go動態(tài)限制并發(fā)數(shù)量的實(shí)現(xiàn)示例

    go動態(tài)限制并發(fā)數(shù)量的實(shí)現(xiàn)示例

    本文主要介紹了Go并發(fā)控制方法,通過帶緩沖通道和第三方庫實(shí)現(xiàn)并發(fā)數(shù)量限制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • Golang設(shè)計(jì)模式工廠模式實(shí)戰(zhàn)寫法示例詳解

    Golang設(shè)計(jì)模式工廠模式實(shí)戰(zhàn)寫法示例詳解

    這篇文章主要為大家介紹了Golang 工廠模式實(shí)戰(zhàn)寫法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • go語言讀取csv文件并輸出的方法

    go語言讀取csv文件并輸出的方法

    這篇文章主要介紹了go語言讀取csv文件并輸出的方法,實(shí)例分析了go語言操作csv文件的技巧,需要的朋友可以參考下
    2015-03-03
  • go使用net/url包來解析URL提取主機(jī)部分

    go使用net/url包來解析URL提取主機(jī)部分

    這篇文章主要為大家介紹了go使用net/url包來解析URL提取主機(jī)部分實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Golang易錯(cuò)知識點(diǎn)匯總

    Golang易錯(cuò)知識點(diǎn)匯總

    這篇文章匯總了在開發(fā)和刷面試題過程中遇到的Golang容易搞錯(cuò)的知識點(diǎn),關(guān)鍵部分也都為大家寫了代碼示例,感興趣的小伙伴可以了解一下
    2022-09-09
  • Go FX框架用法小結(jié)

    Go FX框架用法小結(jié)

    Go FX是一個(gè)功能強(qiáng)大的框架,通過依賴注入和生命周期管理來簡化應(yīng)用的構(gòu)建與維護(hù),本文就來介紹一下Go FX框架用法小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • go嵌套匿名結(jié)構(gòu)體的初始化詳解

    go嵌套匿名結(jié)構(gòu)體的初始化詳解

    這篇文章主要介紹了go嵌套匿名結(jié)構(gòu)體的初始化詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論

定西市| 连江县| 常宁市| 吉隆县| 海原县| 宁陵县| 宜丰县| 全南县| 富宁县| 涟水县| 莱西市| 高清| 黔南| 喀喇沁旗| 乌审旗| 会泽县| 定结县| 长治市| 邛崃市| 静乐县| 全州县| 新晃| 新晃| 遂川县| 汕尾市| 扶绥县| 宁波市| 金沙县| 米泉市| 襄垣县| 和林格尔县| 栖霞市| 岳西县| 老河口市| 秦皇岛市| 石门县| 天气| 循化| 沁阳市| 三门峡市| 行唐县|