亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解golang的切片擴(kuò)容機(jī)制

 更新時(shí)間:2023年07月17日 08:43:25   作者:小小的蒟蒻  
golang的切片擴(kuò)容機(jī)制是golang面試者繞不開的一扇大門,無(wú)論在面試提問,或者面試情景上都繞不開它,今天就說(shuō)說(shuō)我理解下的切片擴(kuò)容機(jī)制,感興趣的小伙伴跟著小編一起來(lái)看看吧

前言

golang的擴(kuò)容機(jī)制:在go1.18之前有一個(gè)臨界值為1024,小于1024的時(shí)候,切片先兩倍擴(kuò)容,如果兩倍擴(kuò)容后的容量還是不夠,就直接以切片需要的容量作為容量。

在go1.18之后,臨界值換成了256,小于256和前面相同,大于256公式變?yōu)椋╫ldcap+3*256)/4這個(gè)公式的值隨著oldcap的越來(lái)越大,從2一直接近1.25,相對(duì)于1.18之前可以更平滑的過(guò)渡。

上面就是切片擴(kuò)容的基本規(guī)則機(jī)制,但還有一個(gè)小的規(guī)則,下面就來(lái)看看

發(fā)現(xiàn)問題

看下面一行代碼

運(yùn)行結(jié)果如下

出現(xiàn)上面的結(jié)果原因是,剛開始切片容量為1,兩倍擴(kuò)容之后,變?yōu)?,但是2不夠,所以變?yōu)樗枰娜萘?,后面在加4個(gè)數(shù)字,繼續(xù)擴(kuò)容,2倍之后是6,但是6不夠應(yīng)該變?yōu)樾枰娜萘浚瑧?yīng)該為7,為什么是8呢

解決問題

先貼一下源代碼,下面第一段代碼是擴(kuò)容機(jī)制的基礎(chǔ)代碼(1.18之前)

下面是造成上面原因的代碼

下面是1.18之后的基礎(chǔ)擴(kuò)容機(jī)制

從上面代碼分析之后,造成7變成8的原因就在這個(gè)roundupsize函數(shù)上面,它有一個(gè)計(jì)算公式

capmem = roundupsize(uintptr(newcap) * ptrSize)
newcap = int(capmem / ptrSize)

其中 ptrSize 在 64 位機(jī)器下的大小為 8。 而此時(shí) newcap 的值為 7,所以傳入到 roundupsize 函數(shù)內(nèi)部的值為 7 * 8 = 56 。接著看看 roundupsize 的內(nèi)部:

func roundupsize(size uintptr) uintptr {
	if size < _MaxSmallSize {
		if size <= smallSizeMax-8 {
			return uintptr(class_to_size[size_to_class8[(size+smallSizeDiv-1)/smallSizeDiv]])
		} else {
			//……
		}
	}
    //……
}
const _MaxSmallSize = 32768
const smallSizeMax = 1024
const smallSizeDiv = 8
var size_to_class8 = [smallSizeMax/smallSizeDiv + 1]uint8{0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}
var class_to_size = [_NumSizeClasses]uint16{0, 8, 16,,24,32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2688, 3072, 3200, 3456, 4096, 4864, 5376, 6144, 6528, 6784, 6912, 8192, 9472, 9728, 10240, 10880, 12288, 13568, 14336, 16384, 18432, 19072, 20480, 21760, 24576, 27264, 28672, 32768}

roundupsize 的返回值為 uintptr(class_to_size[size_to_class8[(size+smallSizeDiv-1)/smallSizeDiv]]),而:

  • (size+smallSizeDiv-1)/smallSizeDiv = (56 + 8 - 1) / 8 = 7
  • size_to_class8[7] = 5
  • class_to_size[5] = 64 所以 roundopsize 的返回值為 64 ,newcap = int(capmem / ptrSize) = int(64 / 8) = 8 ,所以最終原切片的容量擴(kuò)充到了 8。

總結(jié)

如果以后遭遇情景題我們按照這個(gè)公式算的話很費(fèi)時(shí)間,所以我總結(jié)了一下規(guī)則,就是如果遇見2倍擴(kuò)容之后不夠需要直接用它所需要的容量的情況,如果是1和3,它的容量可以是1和3,但如果是5,7,9,11等其他的奇數(shù),全部取+1得到離他最近的偶數(shù),因?yàn)檫@個(gè)值與class_to_size有關(guān),class_to_size全部存的是8的倍數(shù),把class_to_size里面的值全部除以8,結(jié)果為:0,1,2,3,4,6,8,10...........和咱們的規(guī)律非常吻合

到此這篇關(guān)于詳解golang的切片擴(kuò)容機(jī)制的文章就介紹到這了,更多相關(guān)golang切片擴(kuò)容機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 用gin開發(fā)的golang項(xiàng)目三種開發(fā)模式方式

    用gin開發(fā)的golang項(xiàng)目三種開發(fā)模式方式

    這篇文章主要介紹了用gin開發(fā)的golang項(xiàng)目三種開發(fā)模式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • golang利用redis和gin實(shí)現(xiàn)保存登錄狀態(tài)校驗(yàn)登錄功能

    golang利用redis和gin實(shí)現(xiàn)保存登錄狀態(tài)校驗(yàn)登錄功能

    這篇文章主要介紹了golang利用redis和gin實(shí)現(xiàn)保存登錄狀態(tài)校驗(yàn)登錄功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-01-01
  • Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情

    Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情

    這篇文章主要介紹了?Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情,二叉樹是一種數(shù)據(jù)結(jié)構(gòu),在每個(gè)節(jié)點(diǎn)下面最多存在兩個(gè)其他節(jié)點(diǎn)。即一個(gè)節(jié)點(diǎn)要么連接至一個(gè)、兩個(gè)節(jié)點(diǎn)或不連接其他節(jié)點(diǎn),下文基于GO語(yǔ)言展開二叉樹結(jié)構(gòu)詳情,需要的朋友可以參考一下
    2022-05-05
  • golang 通過(guò)ssh代理連接mysql的操作

    golang 通過(guò)ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過(guò)ssh代理連接mysql的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go+Redis緩存設(shè)計(jì)與優(yōu)化實(shí)現(xiàn)

    Go+Redis緩存設(shè)計(jì)與優(yōu)化實(shí)現(xiàn)

    本文主要介紹了Go+Redis緩存設(shè)計(jì)與優(yōu)化實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • 從源碼解析golang Timer定時(shí)器體系

    從源碼解析golang Timer定時(shí)器體系

    本文詳細(xì)介紹了Go語(yǔ)言中的Timer和Ticker的使用方式、錯(cuò)誤使用方式以及底層源碼實(shí)現(xiàn),Timer是一次性的定時(shí)器,而Ticker是循環(huán)定時(shí)器,正確使用時(shí)需要注意返回的channel和垃圾回收問題,Go 1.23版本對(duì)定時(shí)器進(jìn)行了改進(jìn),優(yōu)化了垃圾回收和停止、重置相關(guān)方法
    2025-01-01
  • 深入探討Golang中如何進(jìn)行并發(fā)發(fā)送HTTP請(qǐng)求

    深入探討Golang中如何進(jìn)行并發(fā)發(fā)送HTTP請(qǐng)求

    在?Golang?領(lǐng)域,并發(fā)發(fā)送?HTTP?請(qǐng)求是優(yōu)化?Web?應(yīng)用程序的一項(xiàng)重要技能,本文探討了實(shí)現(xiàn)此目的的各種方法,文中的示例代碼講解詳細(xì),希望對(duì)大家有所幫助
    2024-01-01
  • go?語(yǔ)言爬蟲庫(kù)goquery的具體使用

    go?語(yǔ)言爬蟲庫(kù)goquery的具體使用

    GoQuery是專為Go語(yǔ)言設(shè)計(jì)的一個(gè)強(qiáng)大的HTML解析和查詢庫(kù),本文主要介紹了go語(yǔ)言爬蟲庫(kù)goquery的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • golang多次讀取http request body的問題分析

    golang多次讀取http request body的問題分析

    這篇文章主要給大家分析了golang多次讀取http request body的問題,文中通過(guò)代碼示例和圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • Golang?Time包與日期函數(shù)的用法詳解

    Golang?Time包與日期函數(shù)的用法詳解

    在golang中,time包提供了時(shí)間的顯示和測(cè)量用的函數(shù),下面小編就來(lái)和大家詳細(xì)聊聊Golang中Time包與日期函數(shù)的具體用法,快跟隨小編一起學(xué)習(xí)一下吧
    2023-07-07

最新評(píng)論