golang 切片扩容的探讨

RenXiangCode · · 2645 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang 切片扩容的探讨

分以下几种情况:
1.切片每次新增个数不超过原来的1倍,且每次增加数不超过1024个,且增加后总长度小于1024个,这种情况下扩容后为原来的2倍

    s1 := make([]int, 0)
    fmt.Printf("The capacity of s1: %d\n", cap(s1))
    for i := 1; i <= 17; i++ {
        s1 = append(s1, i)
        fmt.Printf("s1(%d): len: %d, cap: %d\n", i, len(s1), cap(s1))
    }
    fmt.Println()
结果:
/*
The capacity of s1: 0
s1(1): len: 1, cap: 1
s1(2): len: 2, cap: 2
s1(3): len: 3, cap: 4
s1(4): len: 4, cap: 4
s1(5): len: 5, cap: 8
s1(6): len: 6, cap: 8
s1(7): len: 7, cap: 8
s1(8): len: 8, cap: 8
s1(9): len: 9, cap: 16
s1(10): len: 10, cap: 16
s1(11): len: 11, cap: 16
s1(12): len: 12, cap: 16
s1(13): len: 13, cap: 16
s1(14): len: 14, cap: 16
s1(15): len: 15, cap: 16
s1(16): len: 16, cap: 16
s1(17): len: 17, cap: 32
*/

2.切片一次新增个数超过原来1倍,但不超过1024个,且增加后总长度小于1024个,这种情况下扩容后比实际具有的总长度还要大一些。

    s2 := make([]int, 10)
    fmt.Printf("The capacity of s2: %d\n", cap(s2))
    r1 := append(s2, make([]int, 5)...)
    fmt.Printf("r1: len: %d, cap: %d\n", len(r1), cap(r1))
    r2 := append(s2, make([]int, 11)...)
    fmt.Printf("r2: len: %d, cap: %d\n", len(r2), cap(r2))
    r3 := append(s2, make([]int, 21)...)
    fmt.Printf("r3: len: %d, cap: %d\n", len(r3), cap(r3))
    fmt.Printf("注意:像r2,r3 一次增加个数超过原容量的1倍,增加后结果比实际总长度预想的稍大一点 \n")
    fmt.Println()
结果:
/*
The capacity of s2: 10
r1: len: 15, cap: 20
r2: len: 21, cap: 22
r3: len: 31, cap: 32
注意:像r2,r3 一次增加个数超过原容量的1倍,增加后结果比实际总长度预想的稍大一点 
*/

3.原切片长度超过1024时,一次增加容量不是2倍而是0.25倍,每次超过预定的都是0.25累乘

    // 1024 * 0.25 = 256
    s3 := make([]int, 1024)
    fmt.Printf("The capacity of s3: %d\n", cap(s3))
    r4 := append(s3, make([]int, 200)...)
    fmt.Printf("r4: len: %d, cap: %d\n", len(r4), cap(r4))
    r5 := append(s3, make([]int, 256)...)
    fmt.Printf("r5: len: %d, cap: %d\n", len(r5), cap(r5))
    // 1280 * 0.25 = 320
    r6 := append(s3, make([]int, 266)...)
    fmt.Printf("r6: len: %d, cap: %d\n", len(r6), cap(r6))
    fmt.Printf("注意:像r6 一次增加个数超过原容量的0.25倍,增加后结果比原容量1.25倍预想的稍大一点 \n")
    fmt.Println()
结果:
/*
The capacity of s3: 1024
r4: len: 1224, cap: 1280
r5: len: 1280, cap: 1280
r6: len: 1290, cap: 1696
注意:像r6 一次增加个数超过原容量的0.25倍,增加后结果比原容量1.25倍预想的稍大一点
*/

说明下:第三种情况,又分为两种,一种是原长度不小于1024时,一次扩容后为原来的1.25倍(当然一次增加的个数不超过原长度的0.25倍);第二种情况就是一次增加个数超过原长度的0.25倍,扩容后其容量比预想的总长度稍大点,就比如 r6: len: 1290, cap: 1696, 一次扩容长度大于0.25倍,扩容后,其实际容量比0.25累乘预想的大一点,比如10241.251.25 = 1600 ,实际为1696.

示例代码保存在GitHub地址:点击


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:RenXiangCode

查看原文:golang 切片扩容的探讨

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2645 次点击  
加入收藏 微博
1 回复  |  直到 2018-11-09 14:49:19
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传