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

詳解Go語(yǔ)言中切片的長(zhǎng)度與容量的區(qū)別

 更新時(shí)間:2022年11月02日 11:01:14   作者:TimLiu  
切片可以看成是數(shù)組的引用,切片的長(zhǎng)度是它所包含的元素個(gè)數(shù)。切片的容量是從它的第一個(gè)元素到其底層數(shù)組元素末尾的個(gè)數(shù)。本文將通過(guò)示例詳細(xì)講講Go語(yǔ)言中切片的長(zhǎng)度與容量的區(qū)別,需要的可以參考一下

切片的聲明

切片可以看成是數(shù)組的引用(實(shí)際上切片的底層數(shù)據(jù)結(jié)構(gòu)確實(shí)是數(shù)組)。在 Go 中,每個(gè)數(shù)組的大小是固定的,不能隨意改變大小,切片可以為數(shù)組提供動(dòng)態(tài)增長(zhǎng)和縮小的需求,但其本身并不存儲(chǔ)任何數(shù)據(jù)。

// 數(shù)組的聲明
var a [5]int //只指定長(zhǎng)度,元素初始化為默認(rèn)值0
var a [5]int{1,2,3,4,5}

// 切片的聲明
// 方法1:直接初始化
var s []int //聲明一個(gè)長(zhǎng)度和容量為 0 的 nil 切片
var s []int{1,2,3,4,5} // 同時(shí)創(chuàng)建一個(gè)長(zhǎng)度為5的數(shù)組
// 方法2:用make()函數(shù)來(lái)創(chuàng)建切片
var s = make([]int, 0, 5)

// 切分?jǐn)?shù)組:var 變量名 []變量類(lèi)型 = arr[low, high],low和high為數(shù)組的索引。
// 記住規(guī)則為:左閉右開(kāi)
var arr = [5]int{1,2,3,4,5}
var slice []int = arr[1:4] // [2,3,4]

切片的長(zhǎng)度和容量

切片的長(zhǎng)度是它所包含的元素個(gè)數(shù)。切片的容量是從它的第一個(gè)元素到其底層數(shù)組元素末尾的個(gè)數(shù)。切片 s 的長(zhǎng)度和容量可通過(guò)表達(dá)式 len(s) 和 cap(s) 來(lái)獲取。

s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(s, len(s), cap(s))
// output: [0 1 2 3 4 5 6 7 8 9] 10 10

s1 := s[0:5]
fmt.Println(s1, len(s1), cap(s1))
// output: [0 1 2 3 4] 5 10

s2 := s[5:]
fmt.Println(s2, len(s2), cap(s2))
// output: [5 6 7 8 9] 5 5

切片追加元素后長(zhǎng)度和容量的變化

append 函數(shù)

Go 提供了內(nèi)建的 append 函數(shù),為切片追加新的元素。

func append(s []T, vs ...T) []T

append 的返回值是一個(gè)包含原切片所有元素加上新添加元素的切片。

s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(s, len(s), cap(s))
sResult := append(s, 11)
fmt.Println(sResult, len(sResult), cap(sResult))
// output: 
// [0 1 2 3 4 5 6 7 8 9] 10 10
// [0 1 2 3 4 5 6 7 8 9 11] 11 20

這個(gè)時(shí)候,我們就可以發(fā)現(xiàn),當(dāng)我們 append 元素進(jìn)入切片時(shí),原切片的長(zhǎng)度以及容量都發(fā)生了變化,但是它們的變化為什么會(huì)這樣呢?

下面我們一起看看源碼是怎么實(shí)現(xiàn)的。

切片的源代碼學(xué)習(xí)

Go 中切片的數(shù)據(jù)結(jié)構(gòu)可以在源碼下的 src/runtime/slice.go 中查看。以下源代碼基于 go1.16.7 版本。

切片的結(jié)構(gòu)體

切片作為數(shù)組的引用,有三個(gè)屬性字段:指向數(shù)組的指針、長(zhǎng)度和容量。

type slice struct {
  // 指向底層數(shù)組的指針
	array unsafe.Pointer
  // slice 當(dāng)前元素個(gè)數(shù),即 len() 時(shí)返回的數(shù)
	len   int
  // slice 的容量,即 cap() 時(shí)返回的數(shù)
	cap   int
}

切片的擴(kuò)容

slice 通過(guò)調(diào)用 append 函數(shù)來(lái)針對(duì)slice進(jìn)行尾部追加元素,如果此時(shí) slice 的 cap 值小于當(dāng)前 len 加上 append 中傳入值的數(shù)量,就會(huì)調(diào)用 runtime.growslice 函數(shù),進(jìn)行擴(kuò)容。

我們這里只放出基本的擴(kuò)容規(guī)則的代碼解析,如果對(duì)內(nèi)存對(duì)齊、數(shù)據(jù)拷貝等感興趣,可自行查看對(duì)應(yīng)的源碼。

基本擴(kuò)容規(guī)則

func growslice(et *_type, old slice, cap int) slice {
    newcap := old.cap
    doublecap := newcap + newcap
    // 如果新容量大于舊容量的兩倍,則直接按照新容量大小申請(qǐng)
    if cap > doublecap {
			newcap = cap
    } else {
        // 如果原有長(zhǎng)度小于1024,則新容量是舊容量的2倍
        if old.len < 1024 {
            newcap = doublecap
        } else {
            // 按照原有容量的 1/4 增加,直到滿(mǎn)足新容量的需要
            for 0 < newcap && newcap < cap {
                newcap += newcap / 4
            }
            if newcap <= 0 {
                newcap = cap
            }
        }
    }
}

從源碼來(lái)看,實(shí)際上可以整理出幾個(gè)規(guī)則:

當(dāng)原切片長(zhǎng)度小于 1024 時(shí),新的切片長(zhǎng)度直接加上 append 元素的個(gè)數(shù),容量則會(huì)直接 *2

當(dāng)原切片長(zhǎng)度大于等于 1024 時(shí),新的切片長(zhǎng)度直接加上 append 元素的個(gè)數(shù),容量則會(huì)增加 1/4

總結(jié)

切片是一個(gè)結(jié)構(gòu)體,保存著切片的容量,長(zhǎng)度以及指向數(shù)組的指針(數(shù)組的地址)。

從源碼來(lái)看,當(dāng)一個(gè)切片進(jìn)行擴(kuò)容時(shí),會(huì)進(jìn)行 growslice,這是一個(gè)花銷(xiāo)較大的操作,在日常開(kāi)發(fā)中,如果能明確知道切片的長(zhǎng)度或者容量時(shí),我們需要在初始化的時(shí)候聲明,避免切片頻繁擴(kuò)容而帶來(lái)的花銷(xiāo)。

到此這篇關(guān)于詳解Go語(yǔ)言中切片的長(zhǎng)度與容量的區(qū)別的文章就介紹到這了,更多相關(guān)Go語(yǔ)言 切片長(zhǎng)度與容量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用Go語(yǔ)言實(shí)現(xiàn)輕量級(jí)OpenLdap弱密碼檢測(cè)工具

    利用Go語(yǔ)言實(shí)現(xiàn)輕量級(jí)OpenLdap弱密碼檢測(cè)工具

    這篇文章主要為大家詳細(xì)介紹了如何利用Go語(yǔ)言實(shí)現(xiàn)輕量級(jí)OpenLdap弱密碼檢測(cè)工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下
    2022-09-09
  • 詳解Go語(yǔ)言中的作用域和變量隱藏

    詳解Go語(yǔ)言中的作用域和變量隱藏

    這篇文章主要為大家介紹了Go語(yǔ)言中的作用域和變量隱藏,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,感興趣的小伙伴可以了解一下
    2022-04-04
  • go?doudou開(kāi)發(fā)gRPC服務(wù)快速上手實(shí)現(xiàn)詳解

    go?doudou開(kāi)發(fā)gRPC服務(wù)快速上手實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了go?doudou開(kāi)發(fā)gRPC服務(wù)快速上手實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Go基礎(chǔ)教程系列之defer、panic和recover詳解

    Go基礎(chǔ)教程系列之defer、panic和recover詳解

    這篇文章主要介紹了Go基礎(chǔ)教程系列之defer、panic和recover,需要的朋友可以參考下
    2022-04-04
  • 一文帶你了解Golang中的并發(fā)性

    一文帶你了解Golang中的并發(fā)性

    并發(fā)是一個(gè)很酷的話(huà)題,一旦你掌握了它,就會(huì)成為一筆巨大的財(cái)富。所以本文就來(lái)和大家一起來(lái)聊聊Golang中的并發(fā)性,感興趣的可以了解一下
    2023-03-03
  • Go語(yǔ)言中重構(gòu)的技巧分享

    Go語(yǔ)言中重構(gòu)的技巧分享

    這篇文章主要來(lái)和大家分享一下Go語(yǔ)言中重構(gòu)的技巧,即如何盡量避免使用 else、break 和 continue,從而讓代碼更透明、更易讀,感興趣的小伙伴可以學(xué)習(xí)一下
    2023-10-10
  • GO語(yǔ)言常用的文件讀取方式

    GO語(yǔ)言常用的文件讀取方式

    這篇文章主要介紹了GO語(yǔ)言常用的文件讀取方式,涉及一次性讀取、分塊讀取與逐行讀取等方法,是非常實(shí)用的技巧,需要的朋友可以參考下
    2014-12-12
  • Go語(yǔ)言break跳轉(zhuǎn)語(yǔ)句怎么使用

    Go語(yǔ)言break跳轉(zhuǎn)語(yǔ)句怎么使用

    這篇文章主要介紹了Go語(yǔ)言break跳轉(zhuǎn)語(yǔ)句怎么使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • Go基礎(chǔ)系列:Go切片(分片)slice詳解

    Go基礎(chǔ)系列:Go切片(分片)slice詳解

    這篇文章主要介紹了Go語(yǔ)言中的切片(分片)slice詳細(xì)說(shuō)明?,需要的朋友可以參考下
    2022-04-04
  • Golong字符串拼接性能優(yōu)化及原理介紹

    Golong字符串拼接性能優(yōu)化及原理介紹

    最近在做性能優(yōu)化,有個(gè)函數(shù)里面的耗時(shí)特別長(zhǎng),看里面的操作大多是一些字符串拼接的操作,而字符串拼接在 golang 里面其實(shí)有很多種實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于Golang語(yǔ)言如何高效拼接字符串的相關(guān)資料,需要的朋友可以參考下
    2023-04-04

最新評(píng)論

磴口县| 尉氏县| 平利县| 普定县| 舒兰市| 邢台市| 河南省| 房山区| 吉木萨尔县| 城市| 陇西县| 望奎县| 五常市| 锡林郭勒盟| 常宁市| 青田县| 体育| 海南省| 疏勒县| 富川| 齐河县| 方山县| 柘城县| 自治县| 繁峙县| 克什克腾旗| 津市市| 兴安县| 连南| 平谷区| 隆安县| 桑植县| 普陀区| 莆田市| 屯门区| 绿春县| 特克斯县| 常德市| 芜湖市| 高台县| 乌鲁木齐市|