欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Golang 切片(slice)擴(kuò)容機(jī)制的原理

 更新時(shí)間:2021年06月09日 09:07:12   作者:Linux猿  
我們知道 Golang 切片在容量不足的情況下會(huì)進(jìn)行擴(kuò)容,擴(kuò)容的原理是怎樣的呢,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

我們知道 Golang 切片(slice) 在容量不足的情況下會(huì)進(jìn)行擴(kuò)容,擴(kuò)容的原理是怎樣的呢?是不是每次擴(kuò)一倍?下面我們結(jié)合源碼來(lái)告訴你答案。

一、源碼

Version : go1.15.6  src/runtime/slice.go

//go1.15.6 源碼 src/runtime/slice.go
func growslice(et *_type, old slice, cap int) slice {
 //省略部分判斷代碼
    //計(jì)算擴(kuò)容部分
    //其中,cap : 所需容量,newcap : 最終申請(qǐng)容量
 newcap := old.cap
 doublecap := newcap + newcap
 if cap > doublecap {
  newcap = cap
 } else {
  if old.len < 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
   }
  }
 } 
 //省略部分判斷代碼
}

二、原理

1. 如果當(dāng)前所需容量 (cap) 大于原先容量的兩倍 (doublecap),則最終申請(qǐng)容量(newcap)為當(dāng)前所需容量(cap);

2. 如果<條件1>不滿足,表示當(dāng)前所需容量(cap)不大于原容量的兩倍(doublecap),則進(jìn)行如下判斷;

3. 如果原切片長(zhǎng)度(old.len)小于1024,則最終申請(qǐng)容量(newcap)等于原容量的兩倍(doublecap);

4. 否則,最終申請(qǐng)容量(newcap,初始值等于 old.cap)每次增加 newcap/4,直到大于所需容量(cap)為止,然后,判斷最終申請(qǐng)容量(newcap)是否溢出,如果溢出,最終申請(qǐng)容量(newcap)等于所需容量(cap);

這樣說(shuō)大家可能不太明白,來(lái)幾個(gè)例子:

2.1 實(shí)例1

驗(yàn)證條件1:

package main
 
import "fmt"
 
func main() {
 //第1條中的例子:
 var slice = []int{1, 2, 3}
 var slice1 = []int{4, 5, 6, 7, 8, 9, 10, 11, 12}
 fmt.Printf("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice))
 fmt.Printf("slice1 %v len = %v cap = %v\n", slice1, len(slice1), cap(slice1))
 slice = append(slice, slice1...)
 fmt.Printf("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice))
}

輸出:

[root@localhost test]# go run main.go
slice [1 2 3] len = 3 cap = 3
slice1 [4 5 6 7 8 9 10 11 12] len = 9 cap = 9
slice [1 2 3 4 5 6 7 8 9 10 11 12] len = 12 cap = 12
[root@localhost test]#

在實(shí)例1中,所需容量 cap = 9+3 = 12,原容量的兩倍 doublecap = 2 * 3 = 6,滿足 <條件1> 即:所需容量大于原容量的兩倍,所以最終申請(qǐng)容量 newcap = cap = 12。

2.2 實(shí)例2

驗(yàn)證條件2,3:

package main
import "fmt"
 
func main() {
 //第2、3條中的例子:
 var slice = []int{1, 2, 3, 4, 5, 6, 7}
 var slice1 = []int{8, 9}
 fmt.Printf("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice))
 fmt.Printf("slice1 %v len = %v cap = %v\n", slice1, len(slice1), cap(slice1))
 slice = append(slice, slice1...)
 fmt.Printf("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice))
}

 輸出:

[root@localhost test]# go run main.go
slice [1 2 3 4 5 6 7] len = 7 cap = 7
slice1 [8 9] len = 2 cap = 2
slice [1 2 3 4 5 6 7 8 9] len = 9 cap = 14
[root@localhost test]#

在實(shí)例2中,所需容量 cap = 7+2 = 9,原容量的兩倍 doublecap = 2*7 = 14,原切片長(zhǎng)度 old.len = 7,滿足 <條件2,3>,即: 所需容量小于原容量的兩倍,并且原切片長(zhǎng)度 old.len 小于1024,所以,最終申請(qǐng)容量 newcap = doublecap = 14。

2.3 實(shí)例3

驗(yàn)證條件4:

package main
import "fmt"
 
func main() {
 //第2條中的例子:
 var slice []int
 for i := 0; i < 1024; i++ {
  slice = append(slice, i)
 }
 var slice1 = []int{1024, 1025}
 fmt.Printf("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice))
 fmt.Printf("slice1 %v len = %v cap = %v\n", slice1, len(slice1), cap(slice1))
 slice = append(slice, slice1...)
 fmt.Printf("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice))
}

輸出:

[root@localhost test]# go run main.go
slice [0 1 2 3 4 5 6……1017 1018 1019 1020 1021 1022 1023] len = 1024 cap = 1024
slice1 [1024 1025] len = 2 cap = 2
slice [0 1 2 3 4 5 6……1017 1018 1019 1020 1021 1022 1023 1024 1025] len = 1026 cap = 1280
[root@localhost test]#

在實(shí)例3中,所需容量 cap = 1024+2 = 1026,doublecap = 2048,  old.len = 1024,滿足 <條件4> ,所以,newcap = 1024 + 1024/4 = 1280。

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

相關(guān)文章

  • 利用Go Plugin實(shí)現(xiàn)插件化編程的簡(jiǎn)單方法

    利用Go Plugin實(shí)現(xiàn)插件化編程的簡(jiǎn)單方法

    Golang官方提供了plugin模塊,該模塊可以支持插件開,下面這篇文章主要給大家介紹了關(guān)于如何利用Go Plugin實(shí)現(xiàn)插件化編程的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • golang語(yǔ)言實(shí)現(xiàn)的文件上傳與文件下載功能示例

    golang語(yǔ)言實(shí)現(xiàn)的文件上傳與文件下載功能示例

    這篇文章主要介紹了golang語(yǔ)言實(shí)現(xiàn)的文件上傳與文件下載功能,結(jié)合實(shí)例形式分析了Go語(yǔ)言實(shí)現(xiàn)的文件傳輸相關(guān)操作技巧,需要的朋友可以參考下
    2020-02-02
  • Go語(yǔ)言學(xué)習(xí)之鏈表的使用詳解

    Go語(yǔ)言學(xué)習(xí)之鏈表的使用詳解

    鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過(guò)鏈表中的指針鏈接次序?qū)崿F(xiàn)的。本文將詳細(xì)為大家介紹Go語(yǔ)言中鏈表的使用,感興趣的可以了解一下
    2022-04-04
  • Golang連接Redis數(shù)據(jù)庫(kù)的方法

    Golang連接Redis數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了Golang連接Redis數(shù)據(jù)庫(kù)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • go語(yǔ)言題解LeetCode989數(shù)組形式的整數(shù)加法

    go語(yǔ)言題解LeetCode989數(shù)組形式的整數(shù)加法

    這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode989數(shù)組形式的整數(shù)加法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • goland 設(shè)置注釋模板的過(guò)程圖文詳解

    goland 設(shè)置注釋模板的過(guò)程圖文詳解

    這篇文章主要介紹了goland 設(shè)置注釋模板的過(guò)程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-12-12
  • k8s容器互聯(lián)-flannel?host-gw原理篇

    k8s容器互聯(lián)-flannel?host-gw原理篇

    這篇文章主要為大家介紹了k8s容器互聯(lián)-flannel?host-gw原理篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • GO語(yǔ)言中Chan實(shí)現(xiàn)原理的示例詳解

    GO語(yǔ)言中Chan實(shí)現(xiàn)原理的示例詳解

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中Chan實(shí)現(xiàn)原理的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下
    2023-02-02
  • Go語(yǔ)言如何生成PDF文件實(shí)例探究

    Go語(yǔ)言如何生成PDF文件實(shí)例探究

    這篇文章主要為大家介紹了Go語(yǔ)言生成PDF文件的實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Go??iota?常量基本語(yǔ)法介紹

    Go??iota?常量基本語(yǔ)法介紹

    這篇文章主要介紹了Go?為什么要設(shè)計(jì)?iota?常量,我們介紹了 Go 中 iota 的基本語(yǔ)法。同時(shí)基于歷史資料針對(duì) iota 到底是什么,為什么要這么叫,又有什么用進(jìn)行了一番研究,需要的朋友可以參考下
    2022-06-06

最新評(píng)論