• Go指南_切片的长度与容量


    源地址 https://tour.go-zh.org/moretypes/11

    一、描述

    切片拥有 长度 和 容量

    切片的长度就是它所包含的元素个数。

    切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。

    切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取。

    你可以通过重新切片来扩展一个切片,给它提供足够的容量。试着修改示例程序中的切片操作,向外扩展它的容量,看看会发生什么。

    二、程序运行过程

    1,第一个输出为[2,3,5,7,11,13],长度为6,容量为6;

    2,左指针和右指针同时指向s[0],所以长度为0,容量为0;

    3,左指针指向s[0],右指针指向s[4],由于切片概念是只包含左边元素不包含右边元素,所以长度为4,但左指针在s[0]处,走过0个元素,所以容量仍然为6;

    4,在经历步骤3切片后的基础上,左指针指向s[2],右指针指向最右边,所以长度为2,由于左指针走过两个元素,离最右边还剩4个元素,所以容量为4。

    三、小结

    本文内容最难理解的是切片的容量,我们可以把容量当做成总长度减去左指针走过的元素值,比如:

    s[:0] ——> cap = 6 - 0 =6;

    s[2:] ——> cap = 6 - 2 = 4。

    四、append() 和 copy() 函数

    如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

    下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。

    package main
    
    import "fmt"
    
    func main() {
       var numbers []int
       printSlice(numbers)
    
       /* 允许追加空切片 */
       numbers = append(numbers, 0)
       printSlice(numbers)
    
       /* 向切片添加一个元素 */
       numbers = append(numbers, 1)
       printSlice(numbers)
    
       /* 同时添加多个元素 */
       numbers = append(numbers, 2,3,4)
       printSlice(numbers)
    
       /* 创建切片 numbers1 是之前切片的两倍容量*/
       numbers1 := make([]int, len(numbers), (cap(numbers))*2)
    
       /* 拷贝 numbers 的内容到 numbers1 */
       copy(numbers1,numbers)
       printSlice(numbers1)   
    }
    
    func printSlice(x []int){
       fmt.Printf("len=%d cap=%d slice=%v
    ",len(x),cap(x),x)
    }

    这时我将第18行要增加的元素改为五个,我们可以看到len=7,cap=8

    再进行举例说明

    新建切片并在里面追加元素

    整体过程说明

    1. 创建numbers时,由于里面没有加入任何元素,所以len=0 cap=0 slice=[]
    2. append(numbers, 0)时,向空切片numbers中追加了一个元素,所以len=1 cap=1 slice=[0]
    3. append(numbers, 1)时,向之前的切片numbers中追加了一个元素,按Slice扩容机制,cap翻倍后=2,所以len=2 cap=2 slice=[0 1]
    4. append(numbers, 2,3,4,)时,向之前的切片numbers中追加了三个元素,按Slice扩容机制,cap翻倍后2*3=6,所以len=5 cap=6 slice=[0 1 2 3 4]
    5. append(numbers, 5,6,7,8,9,10)时,向之前的切片numbers中追加了六个元素,按Slice扩容机制,cap翻倍后6*2=12,所以len=11 cap=12 slice=[0 1 2 3 4 5 6 7 8 9 10]
    6. 新建切片numbers2 := append(numbers,11)时,是像之前的切片numbers追加一个元素11,追加后长度为12,容量为12,所以不需要扩容,len=12 cap=12 slice=[0 1 2 3 4 5 6 7 8 9 10 11]
    7. 新建切片numbers3 := append(numbers,12)时,是像之前的切片numbers追加一个元素12,追加后长度为12,容量为12,所以不需要扩容,len=12 cap=12 slice=[0 1 2 3 4 5 6 7 8 9 10 12]
    8. 创建切片numbers1时,由于cap(numbers)*2,所以容量要翻倍,len=11 cap=24 slice=[0 1 2 3 4 5 6 7 8 9 10]

    五、总结

    由此可知,容量随着底层数组长度的变化而不断变化,如果底层数组长度为4,在添加了一个元素后变成5,则容量变为 4*2=8,如果len=12,cap=12,如果追加一个元素后,那么新的cap=2*7=14。

    (切片这块很神奇,我也只是把我遇到的总结下,如果有不足之处希望大家及时提出来,我好及时更新!)

    六、参考资料

    Golang中Slice的append详解

  • 相关阅读:
    团队项目总结
    CVPR顶会论文爬取存入MySQL数据库(标题、摘要、作者、PDF链接和原地址)
    如何做好招聘----CEO如何识别优秀的候选人
    《产品方法论 俞军》 读书笔记总结--2021年的第41/100本
    《增长黑客 sean ellis》 读书笔记总结--2021年的第40/100本
    《参与感 黎万强》 读书笔记总结--2021年的第37/100本
    《领导梯队 拉姆查兰》 读书笔记总结--2021年的第35/100本
    《一本书读懂财报》 读书笔记总结--2021年的第34/100本
    《OKR工作法 克里斯蒂娜沃尔克》精读 读书笔记总结----《创业必读书第13本》--创业第三关做好业务:1.如何做好组织管理的第2本
    《美学思维》 混沌大学商学院第12章 读书笔记总结--2020年的第28/100本
  • 原文地址:https://www.cnblogs.com/OctoptusLian/p/9205326.html
Copyright © 2020-2023  润新知