在Golang中顺序容器有两种,一种是普通的数组,一种是切片。
数组(array)
数组创建方式分为两种,一种是通过字面值,一种是通过new
结果
首先注意到,数组在创建的时候必须是在[ ]中指明了元素个数,或者使用[...]结合{1, 2, 3}来创建也是可以的,因为这样也算是定好了数组中元素个数。同时数组的类型是[N]Type,即大小+类型,也就是说对于一个数组,只有大小和元素类型都相同时才认为他们是同一个类型,才可以互相直接赋值,这样的用法是错误的,编译不过去
go中数组就像C/C++中的原生数组一样是静态的,go中数组的底层结构也就是原生的内存结构,即一段连续的内存,但是在go中关于数组有个非常不同于大部分其他语言的地方:数组在go中是是值类型。
所谓值类型就是在参数传递时不会传值,形参会建立一份关于实参的深拷贝,同类型变量赋值是也会进行一份深拷贝,而不是简单的复制地址
当同类型变量间赋值时
结果
在传递参数时
结果
因此用数组传递数组时应该使用数组指针,如下
结果
切片(slice)
切片是引用类型,先明确它的底层结构
可以看到切片底层是对数组的封装,因此也切片经常用于对数组某一段的截取
其中len指明可读可写的实际长度,cap指明整个切片可用的空间大小,实际长度len后的只能通过切片的专属函数append来在末尾追加,同时要注意接收append的返回值,因为append后完全有可能超过切片底层数组的cap,此时会分配新的底层数组给切片,因此每次append的返回的切片必须被接收,之后应该使用的是这个返回的切片而不是原切片。
对比着数组的创建,看看切片的创建,切片的创建分为两种,一种字面值,一种是使用make,注意不可以使用new
先看通过字面值
结果
通过make
结果
可以看到因为切片是引用类型,其赋值都是浅拷贝即对slice底层结构的简单赋值,因此在传参时相比起数组也能非常方便
结果
其实数组与切片的区别并不能列举出很多来,因为本身都不是什么复杂的结构,但是就是有人弄得不明不白,分不清这个地方创建的是数组还是切片,因此这些基础一定要踏实的弄明白。
简单总结一下数组与切片的区别:
1、数组是切片的底层,是静态的,切片通过封装数组来实现动态
2、数组是值类型,切片是引用类型