Go中的切片

1,切片的介绍和结构

1,切片的结构

切片是作为动态数组的简化版。所以切片的长度可以动态的变化。在Go语言的实践中,因为数组因为不灵活的原因很少使用,因此掌握切片是非常重要的。首先要了解切片的底层结构。

//这是go语言底层结构
type SliceHeader struct {
 Data uintptr  //指针指向底层维护的数组
 Len int      //Len代表切片可使用的容量
 Cap int      //Cap代表切片指向底层数组最大的容量
 }
 

因此对于Slice的结构图

//创建一个切片
var s []int=make([]int,23)

其结构图为
在这里插入图片描述
由于只初始化了切片,因此底层数组默认的值为0。在这个初始化中,len=2,cap=3。因此切片可访问的范围为0~1,如果访问第三个元素的时候,会产生越界的问题。如果想动态扩充数组可以使用append()函数,可以扩充切片的容量。但是当扩充后的Cap>oldCap,又得创建新的数组(这块在第二节会详细讲解)。


2,切片的初始化

切片初始化的方法有许多形式,但是掌握了切片的结构并不难。

//直接创建切片
var s []int=[]int{1,2,3}  //此时cap==len
//类型推断
s:=[]int{1,2,3}
//通过make创建切片
s:=make([]int,2,3) //指定切片的类型,切片的len,切片的cap,cap>=len
//通过new创建
s:=new([]int)  //这种创建方式返回的是指针类型,并且没有给定底层数组,不能直接使用切片。
//通过引用其他数组或者是切片
var arr [3]int=[3]int{1,2,3}
s:=arr[1:2]  //此时切片的cap=2,len=1。cap取决于引用数组的位置

2,切片的扩容问题

1,切片的扩容

切片的扩容问题,当切片通过append()函数对切片进行扩容时。可能会产生数组的拷贝,但是根据不同情形扩容的规则也是不一样的。
直接上案例

s:=[]int{1,2} //此时cap=len=2,
s=append(s,3,4,5) // 此时切片Cap=5

这时我们应该考虑扩充后的cap是否等于5?

在切片动态扩充有这样一个规则。

(1) 当oldCap * 2<Cap时,NewCap=Cap.
(2) 否则有以下两种情形。
(3)oldLen<1024 NewCap=oldCap * 2 (这里的1024指的是切片中元素的数目)
(4)oldLen>1024 NewCap=oldCap * 1.25

此时2*2<5,因此扩充的NewCap为5 ,创建一个新的数组Cap为5,将原来数组的内容拷贝过去 。但是我们只探讨了我们能看到的部分,在操作系统这部分分配了多少内存呢?


2,切片扩容后需要占用多大的内存

此部分的内容参考了B站幼麟实验室up主的视频

从上面那个例子,我们发现扩充后的Cap为5,但是在内存中真的只分配5*int(所占字节大小)的内存吗?答案肯定不是的.这是因为在编程语言之中申请内存并不是直接与操作系统直接干涉,而是和编程语言自身实现的内存管理模块。内存管理模块预先会向操作系统申请一批内存,分成不同的规格管理起来。我们申请内存时会匹配到足够大,并且最接近的规格。
在这里插入图片描述
在64位计算机下,申请5个int型所需的字节位 5 * 8=40字节。此时匹配到48个字节的内存块。这就是go语言中扩容后内存的分配策略


3,切片相关的函数及其注意事项

1,切片的相关的函数

(1)append(),动态的添加元素

s:=[]int{1,2,3}
s=append(s,4,5,6) //append()返回的是一个切片,后面的参数可以为多个

(2)copy(slice1,slice2),切片的拷贝操作,将s2的内容拷贝到s1

s:=[]int{1,2,3}
s2:=make([]int,10)
copy(s2,s)
fmt.Println("s=",s) //input [1,2,3]
fmt.Println("s2=",s2) //input [1,2,3,0,0,0,0,0,0,0]
//我们此时修改s2中的值,看是否会影响到s
s2[0]=9
fmt.Println("s=",s) //input [1,2,3]
fmt.Println("s2=",s2) //input [9,2,3,0,0,0,0,0,0,0]
//从这里我们可以发现,这是一个值拷贝。
//当cap(s2)<cap(s)时,此时只会将s的前cap(s2)数量的元素拷贝到s2

(3)通过append()函数的使用,实现对元素的删除

s:=[]int{1,2,3}
//比如我们删除2
s=append(s[:1],s[2:]...)

fmt.Print("s=",s) //Input  =[1,3]

2,切片的注意事项

(1)在切片的使用当中要尽量降低底层数组的扩容,从第二节我们就知道,切片的扩容可能会导致内存的重新分配,这样大大降低了程序的运行效率。
(2)在切片的使用中也要尽量避免内存泄露,避免一个小的内存引用造成整个内存没有被垃圾回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值