go的切片扩容机制详解

 更新时间:2023年04月03日 09:24:45   作者:走,我们去吹风  
本文主要介绍了go的切片扩容机制详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

扩容策略:如果切片的容量小于 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 切片扩容 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Go语言编程学习golang配置golint

    Go语言编程学习golang配置golint

    这篇文章主要为大家介绍了Go语言编程学习golang配置golint的过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11
  • Golang解析yaml文件操作指南

    Golang解析yaml文件操作指南

    之前一直从事java开发,习惯了使用yaml文件的格式,尤其是清晰的层次结构、注释,下面这篇文章主要给大家介绍了关于Golang解析yaml文件的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • Go Gin中间件的具体使用

    Go Gin中间件的具体使用

    中间件是Gin框架中的一个重要概念,它可以用来处理HTTP请求和响应,或者在处理请求之前和之后执行一些操作,本文主要介绍了Go Gin中间件的具体使用,感兴趣的可以了解一下
    2023-11-11
  • Golang使用gin模板渲染base64图片出现#ZgotmplZ的解决办法

    Golang使用gin模板渲染base64图片出现#ZgotmplZ的解决办法

    这篇文章主要介绍了Golang使用gin模板渲染base64图片出现#ZgotmplZ的的场景复现和解决办法,文中通过代码示例讲解的非常详细,对大家解决问题有一定的帮助,需要的朋友可以参考下
    2024-05-05
  • 使用go的interface案例实现多态范式操作

    使用go的interface案例实现多态范式操作

    这篇文章主要介绍了使用go的interface案例实现多态范式操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 浅谈Go语言中的结构体struct & 接口Interface & 反射

    浅谈Go语言中的结构体struct & 接口Interface & 反射

    下面小编就为大家带来一篇浅谈Go语言中的结构体struct & 接口Interface & 反射。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • GoFrame框架gset交差并补集使用实例

    GoFrame框架gset交差并补集使用实例

    这篇文章主要为大家介绍了GoFrame框架gset交差并补集使用实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Golang实现DFA算法对敏感词过滤功能

    Golang实现DFA算法对敏感词过滤功能

    DFA算法是确定性有限自动机,其特征是,有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,通俗的讲DFA算法就是把你要匹配的做成一颗字典树,然后对你输入的内容进行匹配的过程,本文将利用DFA算法实现敏感词过滤,需要的可以参考一下
    2023-10-10
  • 浅谈go-restful框架的使用和实现

    浅谈go-restful框架的使用和实现

    这篇文章主要介绍了浅谈go-restful框架的使用和实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • 一文带你深入理解Golang Context包

    一文带你深入理解Golang Context包

    在 Go 语言中,Context 包是一种非常常用的工具,它被用来管理 goroutine 之间的通信和取消。本文将深入探讨Context 包的基本原理,包括使用场景、原理和一些最佳实践,需要的可以参考下
    2023-05-05

最新评论