精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Go 語言切片擴容規則是擴容2倍?1.25倍?到底幾倍

開發 前端
如果當前傳入的cap是比原有切片cap的2倍還要大,那么就會按照當前傳入的cap來作為新切片的容量,否則去校驗原有切片的容量是否小于 1024。

切片,相信大家用了 Go 語言那么久這這種數據類型并不陌生,但是平日里聊到關于切片是如何擴容的,很多人可能會張口就來,切片擴容的時候,如果老切片的容量小于 1024 那么就再擴容 1倍,也就是新的切片容量是老切片容量的兩倍,同理,如果老切片容量大于 1024,那么就擴容1.25 倍

一個人這么說,多個人這么說,你可能就信了????,可是大家都這么認為,我們就應該盲從嗎?還是要自己去確認真實的擴容邏輯和實現方式,那就開始吧??

結論先行,切片對于擴容并不一定是 2 倍,1.25倍,這個要看實際情況

本文分別從如下幾點來聊聊切片的擴容

  • 擴容是針對切片的,數組無法擴容
  • 切片擴容到底是擴容到原來的幾倍?
  • 我們一般使用切片的時候可以如何避免頻繁的擴容?

擴容是針對切片的,數組無法擴容

首先需要明確,數組是不能擴容的,數組定義的時候就已經是定長的了,無法擴容

切片是可以擴容的,我們可以通過 append 追加的方式來向已有的切片尾部進行追加,若原有切片已滿,那么就會發生擴容

另外,我們知道數組是一段連續的內存地址,同一種數據類型的數據集合,例如這樣

func main() {
   log.SetFlags(log.Lshortfile)
   var demoArray = [5]int{1, 2, 3, 4, 5}
   log.Print("unsafe.sizeof(int) == ",unsafe.Sizeof(demoArray[0]))
   for i, _ := range demoArray {
      log.Printf("&demoAraay[%d] == %p", i, &demoArray[i])
   }
 }

圖片圖片

可以看到在這個案例的環境中,一個 int 類型的變量占用 8 個字節,自然對于 demoArray 數組中,地址是連續的,每一個元素占用的空間也是我們所期望的

那么切片的數據地址也是連續的嗎??

如果有人問這個問題,實際上是想問切片的底層數組的地址是不是也是連續的

我們知道,切片 slice 在 Go 中是一個結構體,其中 array 字段是一個指針,指向了一塊連續的內存地址,也就是底層數組

圖片圖片

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

其中 len 字段記錄了當前底層數組的實際有的元素個數,cap 表示底層數組的容量,自然也是切片slice 的容量

func main(){
    var demoSli = []int{1,2,3,4,5}
    log.Printf("len == %d,cap == %d",len(demoSli),cap(demoSli))
    for i, _ := range demoSli {
       log.Printf("&demoSli[%d] == %p", i, &demoSli[i])
    }
}

圖片圖片

自然,demoSli 中的元素打印出來,地址也是連續的,沒有毛病

此處 xdm 模擬的時候,切勿去打印拷貝值的地址,例如下面這種方式是相當不明智的

圖片圖片

現在簡單的去給 切片追加一個元素

圖片圖片

可以看到切片的容量變成了原來的兩倍(容量從 5 擴容成 10),且切片中底層數組的元素地址自然也是連續的,不需要著急下結論,繼續往下看,好戲在后頭

切片擴容到底是擴容到原來的幾倍?

案例1 向一個cap 為 0 的切片中追加 2000 個元素,查看被擴容了幾次

圖片圖片

總共是擴容了 14 次

可以看到切片容量小于 1024 時,觸發擴容都是擴容到原來的 2 倍,但是 大于 1024 之后,有的是 1.25 倍,有的是 1.35 倍,有的大于 1.35 倍,那么這是為什么呢?后面統一看源碼

案例2 再次驗證切片容量小于 1024,觸發到擴容就一定是擴容 2 倍嗎

  • 先初始化一個切片,里面有 5 個元素,len 為 5,cap 為 5
  • 再向切片中追加 6 個元素,分別是 6,7,8,9,10,11
  • 最終查看切片的容量是多少
func main(){
    var demoSli = []int{1, 2, 3, 4, 5}
    log.Printf("len == %d,cap == %d", len(demoSli), cap(demoSli))
    for i, _ := range demoSli {
       log.Printf("&demoSli[%d] == %p", i, &demoSli[i])
    }
    
    demoSli = append(demoSli,6,7,8,9,10,11)
    log.Printf("len == %d,cap == %d",len(demoSli),cap(demoSli))
    for i, _ := range demoSli {
       log.Printf("&demoSli[%d] == %p", i, &demoSli[i])
    }
}

通過這一段代碼,我們可以看到,講一個 len 為 5,cap 為 5 的切片,追加數字 6 的時候,切片應該要擴容到 10,然后追加到數字 11 的時候,切片應該擴容到 20,可實際真的是這樣嗎?

圖片圖片

xdm 可以將上述 demo 貼到自己環境試試,得到的結果仍然會是切片的容量 cap 最終是 12,并不是 20

那么這一切都是為什么呢?我們來查看源碼一探究竟

源碼賞析

查看公共庫中 runtime/slice.go 的 growslice 函數就可以解開我們的疑惑

圖片圖片

可以看出在我們使用 append 對切片追加元素的時候,實際上會調用到 growslice 函數, growslice 中的核心邏輯我們就可以理解為計算基本的 newcap 和進行字節對齊

  1. 進行基本的新切片容量計算
// 省略部分
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
   newcap = cap
} else {
   if old.cap < 1024 {
      newcap = doublecap
   } else {
      // Check 0 < newcap to detect overflow
      // and prevent an infinite loop.
      for 0 < newcap && newcap < cap {
         newcap += newcap / 4
      }
      // Set newcap to the requested cap when
      // the newcap calculation overflowed.
      if newcap <= 0 {
         newcap = cap
      }
   }
}
// 省略部分

此處邏輯可以知道

  • 如果當前傳入的 cap 是比原有切片 cap 的 2 倍還要大,那么就會按照當前傳入的 cap 來作為新切片的容量
  • 否則去校驗原有切片的容量是否小于 1024

若小于 1024 ,則按照原有的切片容量的 2 倍進行擴容

若大于等于 1024 ,那么就按照原有切片的 1.25 倍繼續擴容

然后是否看到這里就就結束了呢?就下定論來呢?并不,我們切莫斷章取義,需要看全整個流程

  1. 進行基本的字節對齊

growslice 函數 計算出基本的 newcap 之后,還需要按照類型進行基本的字節對齊,此處字節對齊之后主要是 roundupsize 的函數實現,順便將其涉及到的常量放到一起給大家展示一波

const (
   _MaxSmallSize = 32768
   smallSizeDiv = 8
   smallSizeMax = 1024
   largeSizeDiv = 128
   _NumSizeClasses = 68
   _PageShift = 13
)
func roundupsize(size uintptr) uintptr {
   if size < _MaxSmallSize {
      if size <= smallSizeMax-8 {
         return uintptr(class_to_size[size_to_class8[divRoundUp(size, smallSizeDiv)]])
      } else {
         return uintptr(class_to_size[size_to_class128[divRoundUp(size-smallSizeMax, largeSizeDiv)]])
      }
   }
   if size+ _PageSize < size {
      return size
   }
   return alignUp(size, _PageSize)
}

func divRoundUp(n, a uintptr) uintptr {
   // a is generally a power of two. This will get inlined and
   // the compiler will optimize the division.
   return (n + a - 1) / a
}
var size_to_class8 = [smallSizeMax/smallSizeDiv + 1]uint8{0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, ...}

光看這個函數,沒啥感覺,函數邏輯比較簡單,就是基本的計算和索引,那么我們講上述的案例2帶入,來計算一下

圖片圖片

此處很明確,當前舊的切片的 cap 為 5

也就是 growslice 函數 中 old.cap 為 5,傳入的 cap 為 11,因此 cap > 2*old.cap

因此 newcap 此處等于 11

圖片圖片

開始計算字節對齊之后的結果

  • roundupsize(uintptr(newcap) * sys.PtrSize) ,其中 newcap = 11,sys.PtrSize = 8,則 roundupsize 參數傳入 88 ,此環境指針占用 8 字節
  • 按照如下邏輯進行計算

divRoundUp(88, 8) = 11

size_to_class8[11] = 8

class_to_size[8] = 96

此處環境我們的 int 類型是占用 8 個字節,因此最終的 newcap = 96/8 = 12

圖片圖片

經過上述源碼的處理,最終我們就可以正常的得到最終切片容量被擴容到 12 ,xdm 可以去看實際的源碼

小結

使用 append 進行切片擴容的時候,先會按照基本的邏輯來計算 newcap 的大小

  • 如果當前傳入的cap是比原有切片cap的2倍還要大,那么就會按照當前傳入的cap來作為新切片的容量,否則去校驗原有切片的容量是否小于 1024
  • 若小于1024,則按照原有的切片容量的2倍進行擴容
  • 若大于等于 1024,那么就按照原有切片的 1.25 倍繼續擴容最終再進行字節對齊

那么實際上,最終的切片容量一般是會等于或者大于原有的 2倍 或者是 1.25 倍的

我們一般使用切片的時候可以如何避免頻繁的擴容?

一般在使用切片的時候,盡量避免頻繁的去擴容,我們可以對已知數據量的數據,進行一次性去分配切片的容量

例如,數據量有 1000 個,那么我們就可以使用 make 的方式來進行初始化

sli := make([]int, 0, 1000)

本次就是這樣,如果對源碼還挺感興趣的話,xdm 可以去實際查看一下源碼哦,希望對你有幫助

責任編輯:武曉燕 來源: 阿兵云原生
相關推薦

2023-04-03 08:02:16

切片擴容GO

2017-05-27 09:35:56

康復機器人兒童福利院

2021-03-04 09:25:08

Go語言惡意軟件黑客

2018-03-28 14:10:10

GoPython代碼

2021-03-29 15:59:52

區塊鏈比特幣擴容

2020-10-23 06:56:00

C語言動態字符串

2022-10-27 08:31:31

架構

2021-11-19 11:36:42

語言string字符串

2025-04-14 10:10:00

磁盤Linux磁盤擴容

2013-07-10 17:27:07

OTN技術華為OTN華為

2010-09-01 14:00:01

DB2表空間

2023-03-13 13:36:00

Go擴容切片

2022-04-06 08:19:13

Go語言切片

2023-03-29 08:03:53

2025-05-26 01:40:00

2021-06-07 11:40:26

Python命令代碼

2018-08-20 08:15:50

編程語言Go語言切片

2021-07-13 06:44:04

Go語言數組

2022-01-21 14:26:05

區塊鏈鏈上鏈下

2020-07-22 08:30:02

代碼開發工具
點贊
收藏

51CTO技術棧公眾號

日韩精品福利网站| 有码一区二区三区| 国产精品网红福利| 日韩av毛片在线观看| 91成人短视频在线观看| 亚洲激情第一区| 国产欧美日韩综合精品二区| 国产免费av一区二区| 国产探花一区在线观看| 欧美高清性hdvideosex| 亚洲精品乱码久久久久久蜜桃91| 欧美精品一二三四区| 精品国产一二三四区| xxxxx99| 精品国产亚洲一区二区三区| 亚洲欧美日韩中文播放 | 欧美成人一品| 亚洲精品aⅴ中文字幕乱码| 久久久久久三级| 91高清在线观看视频| www.日韩精品| 国产精品成人久久久久| 精品在线观看一区| 久久精品凹凸全集| 91麻豆精品国产91久久久使用方法 | 欧美福利在线播放| 国产女主播一区| 91成人免费观看| 波多野结衣黄色网址| 欧美激情麻豆| 在线精品91av| 亚洲一区二区三区四区五区六区| 成人亚洲网站| 精品久久久中文| 免费观看黄色大片| 国产在线中文字幕| 成人97人人超碰人人99| 91精品免费久久久久久久久| 久草国产精品视频| 精品国产精品| 亚洲精品xxx| 波多野结衣网页| 亚洲精品一区三区三区在线观看| 亚洲第一狼人社区| 永久免费看av| 免费黄色在线| 中文字幕一区二区三中文字幕| 久久久久久亚洲精品不卡4k岛国| 精品国产无码一区二区| 蜜桃久久av一区| 日韩av高清不卡| 久久久精品视频免费观看| 日韩福利视频一区| 亚洲成人激情图| 亚洲欧美综合视频| 日本在线成人| 欧美一区三区四区| 亚洲色图偷拍视频| 日本a人精品| 欧美影院一区二区| 日本特黄a级片| 天然素人一区二区视频| 色偷偷久久人人79超碰人人澡 | 91官网在线| 国产丝袜在线精品| 欧美大陆一区二区| 深夜福利视频在线免费观看| 成人免费毛片嘿嘿连载视频| 99se婷婷在线视频观看| 亚洲第一视频在线播放| 国产成人日日夜夜| 国产精品入口免费| 亚洲欧美另类综合| www.欧美精品一二区| 国产丝袜不卡| 香蕉视频网站在线| 久久久精品一品道一区| 欧美一卡2卡3卡4卡无卡免费观看水多多 | 超碰国产在线| 中文字幕亚洲一区二区va在线| 先锋影音亚洲资源| 麻豆视频在线播放| 一区二区三区蜜桃| 欧美成人高潮一二区在线看| av最新在线| 色综合久久99| 国产一伦一伦一伦| 免费欧美网站| 亚洲精品短视频| 人妻体内射精一区二区| 伊人成综合网yiren22| 国产亚洲欧洲高清一区| 午夜激情视频在线播放| 欧美成人一品| 热久久免费视频精品| 中文字幕第2页| 精品一区二区三区免费视频| 成人三级在线| 精品无吗乱吗av国产爱色| 国产精品素人视频| 免费看日b视频| 日韩av一卡| 欧美日韩亚洲国产综合| 韩国三级在线播放| 亚洲桃色综合影院| 操91在线视频| 日韩av在线播| 麻豆久久久久久| 不卡一区二区三区视频| 免费在线高清av| 国产欧美精品一区| 日韩成人午夜影院| 偷拍精品精品一区二区三区| 日韩一区二区视频在线观看| 免费看黄色aaaaaa 片| 999久久久国产精品| 久久乐国产精品| 波多野结衣视频网址| 高清视频一区二区| 色噜噜一区二区| 51精品视频| 在线观看亚洲精品视频| 动漫av在线免费观看| 欧美91在线| 欧美高清视频免费观看| 中文字幕视频一区二区| av成人免费在线观看| 特级西西人体www高清大胆| 免费电影日韩网站| 这里只有精品视频在线观看| 成人免费网站黄| 欧美深夜福利| 成人福利视频在线观看| 麻豆国产在线播放| 亚洲网友自拍偷拍| 国产欧美一区二| 久久爱www成人| 久久久久久久一区二区三区| 91theporn国产在线观看| 久久众筹精品私拍模特| 黄色三级中文字幕| avtt久久| 色偷偷av一区二区三区乱| 日本一区二区免费电影| av在线一区二区三区| ijzzijzzij亚洲大全| 99久久er| 一区二区三区 在线观看视| 日韩欧美一区二区一幕| 国产99久久久国产精品潘金| 强伦女教师2:伦理在线观看| 日本精品网站| 在线观看国产成人av片| 国产午夜无码视频在线观看| 96av麻豆蜜桃一区二区| 成人午夜视频在线观看免费| 一区视频网站| 日韩最新免费不卡| 国产三级精品三级在线观看| 337p粉嫩大胆色噜噜噜噜亚洲| www精品久久| 岛国成人av| 97在线观看视频国产| 色欲av永久无码精品无码蜜桃| 亚洲一线二线三线视频| 9.1在线观看免费| 亚洲高清激情| 九九99久久| 五月天国产在线| 亚洲美女久久久| 亚洲精品久久久久久久蜜桃| 91丨九色丨尤物| 国产无限制自拍| 久久黄色影视| 国产成人综合精品在线| 高清福利在线观看| 欧美日韩亚洲综合在线| 99自拍视频在线| 国产传媒欧美日韩成人| 三上悠亚久久精品| 日韩av系列| 午夜精品久久久久久久白皮肤| 天天色综合av| 在线视频一区二区三| 手机看片日韩av| 国产一区二区三区视频在线播放| 成人高清dvd| 丝袜av一区| 国产精品久久久久久一区二区| 日本在线免费| 精品久久久久久久久久久久久久久| 久久精品视频久久| 久久综合九色综合欧美98| 手机看片福利日韩| 欧美.日韩.国产.一区.二区| 国产一区二区精品在线| 精品无人乱码一区二区三区| 久久天天躁狠狠躁夜夜av| 国产免费av电影| 性感美女极品91精品| 国产又黄又粗视频| 国产成人免费视频一区| 日本wwww视频| 久久精品青草| 久久精品国产理论片免费| 欧美极品免费| 日韩中文字幕久久| 三级小视频在线观看| 欧美视频中文一区二区三区在线观看 | 99精品视频网站| 日本成人精品| 国产精品久久久久久久久影视| 日本在线视频中文有码| 国产亚洲一区二区在线| 亚洲精品视频91| 欧美日韩一区二区三区四区| 国产精品成人久久| 国产精品沙发午睡系列990531| 人妻换人妻a片爽麻豆| 日av在线不卡| 国产午夜福利在线播放| 亚洲欧美综合久久久| 欧美一二三区| 久久99精品国产自在现线| 国产欧美韩国高清| 麻豆mv在线观看| 欧美黑人巨大xxx极品| 日本在线视频1区| 欧美电影精品一区二区| 在线观看日批视频| 欧美性猛交xxxx| 国产精品111| 一区二区三区免费看视频| 糖心vlog免费在线观看| 久久人人超碰精品| 中文字幕一区二区在线观看视频| 久久久水蜜桃av免费网站| 日韩 欧美 视频| 一本到12不卡视频在线dvd| 色播五月综合| 国产午夜一区| 欧美一级爽aaaaa大片| 日韩精品社区| 激情欧美一区二区三区中文字幕| 欧美高清hd| 青青精品视频播放| 黑人另类精品××××性爽| 久久久国产影院| 瑟瑟视频在线| 中文字幕日韩av电影| 国产成人天天5g影院在线观看 | 免费福利在线观看| 精品国产网站在线观看| 精品人妻少妇嫩草av无码专区| 欧美日本一区二区三区四区| 国产成人精品一区二区色戒| 色婷婷亚洲综合| 日本中文字幕久久| 色www精品视频在线观看| 久久艹免费视频| 亚洲成av人影院| 日本亚洲欧美在线| 亚洲成人精品一区| 韩国av免费观看| 色综合中文字幕国产| 国产午夜精品久久久久| 色先锋aa成人| 日韩精品在线免费视频| 亚洲国产成人高清精品| 影音先锋亚洲天堂| 91国产福利在线| 在线播放精品视频| 在线成人午夜影院| 精品国产乱码久久久久久蜜臀网站| 日韩一卡二卡三卡四卡| 亚洲成人777777| 亚洲精品国产精品自产a区红杏吧| 婷婷在线免费观看| 亚洲色图美腿丝袜| 亚洲精品承认| 欧美日本在线视频中文字字幕| 精品国产99久久久久久| 欧美精品日韩www.p站| 98色花堂精品视频在线观看| 欧美一级bbbbb性bbbb喷潮片| 色是在线视频| 国产精品爽爽爽| 九九九九九九精品任你躁| 福利视频久久| 蜜桃视频欧美| 中文有码久久| 99热这里只有成人精品国产| 日韩有码免费视频| 精品一区二区三区在线视频| 911av视频| av激情亚洲男人天堂| 神马久久久久久久久久久| 亚洲乱码国产乱码精品精98午夜| 日韩和一区二区| 欧美日韩你懂得| 少妇一区二区三区四区| 精品丝袜一区二区三区| 在线观看免费黄色| 欧美精品激情视频| 亚洲a∨精品一区二区三区导航| 91久久爱成人| 美女久久99| 中文字幕日韩一区二区三区| 韩日成人在线| xxxx一级片| 不卡电影一区二区三区| 亚洲天堂av中文字幕| 亚洲精品v日韩精品| 亚洲国产av一区二区三区| 欧美一区二区三区四区高清| 久草福利在线| 欧美激情综合色综合啪啪五月| 日本一区二区三区视频在线| 高清不卡一区二区三区| 日韩国产综合| 国产午夜伦鲁鲁| 国产精品香蕉一区二区三区| 中国女人特级毛片| 色婷婷av一区二区三区大白胸| 深夜福利视频网站| 欧美精品国产精品日韩精品| 欧美成人一级| 欧美黄网在线观看| 国产成人午夜片在线观看高清观看| 三级在线观看免费大全| 欧美乱妇20p| 欧美三级理伦电影| 成人av电影天堂| 亚洲国产精品91| 欧美视频国产视频| 一区在线播放视频| 国产精品久久久久久免费播放 | 国产人妻人伦精品1国产丝袜| 亚洲国产一区二区三区青草影视 | 亚洲精品少妇网址| 天堂中文av在线资源库| 久久综合中文色婷婷| 西西人体一区二区| 欧美熟妇一区二区| 色综合av在线| av电影在线观看网址| 国产欧美日韩免费看aⅴ视频| 日韩在线不卡| 在线视频日韩欧美| 亚洲综合999| 天天干,夜夜操| 日韩美女在线播放| 日韩国产一区| 日本美女久久久| 亚洲国产色一区| 视频国产在线观看| 国产精品久久久久久中文字| 日韩精品一区二区三区免费观影 | 成人国产一区二区三区| 懂色av一区二区三区免费看| 国产精品99无码一区二区| 亚洲欧美福利视频| 韩日精品一区| 九一免费在线观看| 99在线精品免费| 精品一区二三区| 久久伊人免费视频| 91免费精品国偷自产在线在线| 妞干网视频在线观看| 久久夜色精品国产噜噜av| 中文字幕av片| 欧美国产日韩二区| 亚洲人和日本人hd| 日韩av加勒比| 欧美视频国产精品| 免费av在线网址| 国产伦一区二区三区色一情| 久久久久国产一区二区| 蜜桃视频最新网址| 欧美成人午夜电影| 国产精品av一区二区三区| 一本一生久久a久久精品综合蜜| 国产成人福利片| 亚洲婷婷综合网| 欧美成人激情视频| 国产99久久| 国产成人精品一区二区在线小狼| 欧美午夜精品久久久久久浪潮| 嫩草在线视频| 久久国产精品亚洲va麻豆| 久久精品国产第一区二区三区| 国产一级一片免费播放| 在线亚洲国产精品网| 最新国产精品精品视频| 国产wwwxx| 欧美三级免费观看| 亚洲区欧洲区| 日韩中文一区| a美女胸又www黄视频久久| 国产精品自偷自拍|