文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

go的切片扩容机制详解

2023-05-14 08:08

关注

切片的扩容策略?如何扩容?

扩容策略:如果切片的容量小于 1024 个元素,于是扩容的时候就翻倍增加容量。总容量从原来的1个翻倍到现在的2个。

一旦元素个数超过 1024 个元素,那么增长因子就变成 1.25 ,即每次增加原来容量的四分之一。

注意:扩容扩大的容量都是针对原来的容量而言的,而不是针对原来数组的长度而言的。

举一个扩容策略例子:

func main() {
    slice := []int{10, 20, 30, 40}
    newSlice := append(slice, 50)
    fmt.Printf("Before slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice))
    fmt.Printf("Before newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice))
    newSlice[1] += 10
    fmt.Printf("After slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice))
    fmt.Printf("After newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice))
}

// result 
Before slice = [10 20 30 40], Pointer = 0xc4200b0140, len = 4, cap = 4
Before newSlice = [10 20 30 40 50], Pointer = 0xc4200b0180, len = 5, cap = 8
After slice = [10 20 30 40], Pointer = 0xc4200b0140, len = 4, cap = 4
// 相加的数是在新的切片上相加的
After newSlice = [10 30 30 40 50], Pointer = 0xc4200b0180, len = 5, cap = 8

 从结果我们可以看出,新切片和之前的切片已经不同了,因为新的切片更改了一个值,并没有影响到原来的数组,新切片指向的数组是一个全新的数组,并且cap容量也发生了变化。

那么到底是新数组还是老数组呢?
扩容之后数组就一定是新的吗?其实是分两种情况。

第一种情况:

func main() {
    array := [4]int{10, 20, 30, 40}
    slice := array[0:2]
    newSlice := append(slice, 50)
    fmt.Printf("Before slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice))
    fmt.Printf("Before newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice))
    newSlice[1] += 10
    fmt.Printf("After slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice))
    fmt.Printf("After newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice))
    fmt.Printf("After array = %v\n", array)
}

// result
    Before slice = [10 20], Pointer = 0xc4200c0040, len = 2, cap = 4
    Before newSlice = [10 20 50], Pointer = 0xc4200c0060, len = 3, cap = 4
    After slice = [10 30], Pointer = 0xc4200c0040, len = 2, cap = 4
    After newSlice = [10 30 50], Pointer = 0xc4200c0060, len = 3, cap = 4
    After array = [10 30 50 40]

通过这个结果可以明显的看出,修改新切片的值居然影响到了老切片的值了,扩容以后并没有新建一个新的数组,并且append操作也改变了原来数组的值,如果原数组上有多个切片,那么这些切片都会影响,产生了莫名的bug!

这种情况也极容易出现在字面量创建切片时候,第三个参数 cap 传值的时候,如果用字面量创建切片,cap 并不等于指向数组的总容量,那么这种情况就会发生。

注意:建议用字面量创建切片的时候,cap 的值一定要保持清醒,避免共享原数组导致的 bug。

第二种情况:

第二种情况就是扩容策略的例子了,在扩容之后产生了新的切片,因为原数组的容量达到了最大值,再扩容都会开出一片新的内存,把原来的值拷贝过来,再进行后续操作也不会影响原数组。

总结:时刻保持cap的清醒,推荐使用第二种情况的扩容策略

到此这篇关于go的切片扩容机制详解的文章就介绍到这了,更多相关go 切片扩容 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯