zoukankan      html  css  js  c++  java
  • 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]

    由于扩容了两次,没有超过原始数组的容量,所以新切片指针还是指向原始数组,对新切片的修改既对原始数组的修改。从而打印原始数组为修改过的原数组。

  • 相关阅读:
    初始Dubbo
    ProcessBuilder执行本地命令
    Deep Learning的基本思想
    机器学习(Machine Learning)
    Group By和Order By的总结
    Oracle sqlldr命令
    redis的简单操作
    Java程序中做字符串拼接时可以使用的MessageFormat.format
    Bean的作用域
    DI延伸
  • 原文地址:https://www.cnblogs.com/zhoujunjie/p/10824274.html
Copyright © 2011-2022 走看看