golang中数组和切片到底有什么区别?

网站建设4年前发布
156 0 0

数组大家都知道是具有「固定长度及类型的序列集合」,但是golang中又引入了「切片」,语法上看起来还和数组差不多,为什么会引入这些呢?切片和数组到底有什么区别呢?接下来咱们来一个一个的看。,上述语句表示的意思是,我们来定义一个变量arr 为5个长度的int的数组类型,也就是[5]int,同时给赋值上了初始值 1、2、3、4、5,内存分布如图,20230306135801316c1915938c036662d345ceb500d505894d56739,紧密挨在一起的数据结构集合,注意,如果定义数组的方法是;,那么arr的数据类型为*[4]int,而不是[4]int;,当然数组的长度4如果是不固定的,可以用...的方式代替,数组的循环在golang中有一个特有的语法,就是 for  range,常用方法是「len()」 方法和 「cap()」 方法;,但是「在数组中,这两个值永远相同」,所以在这里咱们不多做考虑,在后面切片中再详细阐述。,切片之所以会诞生,是因为golang中数组存在很大的两个问题,固定的长度,这意味着初始化 array 后,不能再 push 超过 len(array) 长度的元素,array 作为参数在函数之间传递时是值传递,相当于把数据copy了一份,具有很大的性能浪费,比如我们定义了一个切片,那么以上变量在内存中的数据结构如下图所示,20230306135815d2a47b054b7ea654ead032264c5a2dd14d55c2525,所以由上面的分析可以看出来,「切片是依赖于数组的,而且是一个指向数组的指针」,既然切片是指针类型,那么在作为参数传递的时候,肯定是引用类型,不需要重新copy一份而造成空间浪费。,我们上面说过切片是依赖于数组的,所以切片的截取是基于数组进行截取的,截取这块我们直接看例子就行,看例子记住一个原则即可「左包含,右不包含」,以上例子都符合上面提到的「左包含,右不包含原则」,长度很好理解,简单理解就是「元素的个数」,容量相对难理解一些「在切片引用的底层数组中从切片的第一个元素到数组最后一个元素的长度就是切片的容量」。,我们还是来直接看例子:,make,make方法主要是用于切片的生成,比较简单,比如下面的例子就是我们来定义一个长度为5,容量为10的切片。,append,append主要是用于切片的追加。我们还是直接看例子。,我们可以看到定义了一个切片,初始化了4个元素,切片此时的长度和容量都为4。,分析:长度由4变成5,我们很好理解;容量为什么会从4变成8呢?「这个是因为go语言对切片的自动扩容机制,append追加,如果cap不够的时候,go底层会把底层数组替换,是go语言的一套扩容策略。」 简单说这个扩容机制就是「如果不够,就在以前的基础上翻倍,如果超过1M,则+1M」,跟redis的bitmap类型的扩容机制是一样的。,slice 扩容的"坑",这个坑在面试中经常会遇到,当 slice 作为函数参数时,「如果在函数内部发生了扩容,这时再修改 slice 中的值是不起作用的」,因为修改发生在新的 array 内存中,对老的 array 内存不起作用。,如何追加多个元素,copy,我们发现s1和s2是[11 2 3] s3是[1 2 3],说明copy方法是复制了一份,开辟了新的内存空间,不再引用s1的内存地址,这就是两者的区别。,如果您觉得这篇文章还不错,记得关注点赞哦,您的支持是我创作的最大动力。

© 版权声明

相关文章