golang中slice的擴容機制


閱讀此文檔默認已經掌握了slice的動態數組原理,如果沒有此認知,請閱讀https://i6448038.github.io/2018/08/11/array-and-slice-principle/ (本文也是在此鏈接基礎上擴展一些解釋說明)。

擴容

slice這種數據結構便於使用和管理數據集合,可以理解為是一種“動態數組”,slice也是圍繞動態數組的概念來構建的。既然是動態數組,那么slice是如何擴容的呢?

請記住以下兩條規則:

  • 如果切片的容量小於1024個元素,那么擴容的時候slice的cap就翻番,乘以2;一旦元素個數超過1024個元素,增長因子就變成1.25,即每次增加原來容量的四分之一。
  • 如果擴容之后,還沒有觸及原數組的容量,那么,切片中的指針指向的位置,就還是原數組,如果擴容之后,超過了原數組的容量,那么,Go就會開辟一塊新的內存,把原來的值拷貝過來,這種情況絲毫不會影響到原數組。

知道了一下規則,請看下面程序,試問輸出結果:

1
2
3
4
5
6
7
8
9
10
import (
"fmt"
)
func main(){
array := [4]int{10, 20, 30, 40}
slice := array[0:2]
newSlice := append(append(append(slice, 50), 100), 150)
newSlice[1] += 1
fmt.Println(slice)
}

輸出:

1
[10 20]

上述程序中,由於擴容了三次,超過了原始數組的容量,所以把原始數組拷貝過來,對新切片的修改並不影響原始數組的值。從而打印原始數組不影響原數組。

 

如果:

1
2
3
4
5
6
7
8
9
10
import (
"fmt"
)
func main(){
array := [4]int{10, 20, 30, 40}
slice := array[0:2]
newSlice := append(append(slice, 50), 100)
newSlice[1] += 1
fmt.Println(slice)
}

 則輸出:

1
[10 21]

由於擴容了兩次,沒有超過原始數組的容量,所以新切片指針還是指向原始數組,對新切片的修改既對原始數組的修改。從而打印原始數組為修改過的原數組。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM