上一章节我们已经了解了数组的特点:数组的长度在定义之后无法再次修改;数组是值类型,每次传递都将产生一份副本。数组的这种特点无法满足特定场景的开发需求,Go语言提供了更为灵活、功能强悍的内置类型——切片(slice)来弥补数组的不足。
切片分为上、下两节。本节介绍切片的基础知识:切片的声明、空切片、切片和数组的区别和关联、切片的创建。
1
切片的声明
切片的声明格式类似于数组,其格式如下:
注:a. “[]”内部没有任何符号,也没有空格;
b. “[]”后面紧跟的是切片元素的类型;
c. 切片中的元素类型统一一致。
2
空切片
如果一个切片仅声明却没有初始化,那么这个切片就叫作空切片。
3
切片和数组的区别
切片和数组在格式声明、本质和同类型之间是否可以比较有区别,如表1所示。
4
切片和底层数组的关联
切片是引用类型,总是指向一个底层数组。但它不是指向底层数组的指针,实际上它拥有自己的数据结构,指针仅仅是其内部数据结构的一部分。如图1所示,切片的数据结构可以抽象为以下3个变量:
♦一个指针:指向底层数组;
♦长度:即切片中的元素个数;
♦容量:即最大长度,切片已分配的存储空间。
从底层实现的角度来看,切片实际上仍然使用数组来管理元素。基于数组,切片添加了一系列管理功能,可以随时动态扩充存放空间。
5
切片的创建
创建切片的方法主要有三种:直接创建切片、基于数组创建新切片、基于已知切片创建新切片。
5.1 直接创建切片
Go语言既可以通过声明和赋值的方式创建切片,也提供了一种内置函数make()用于创建切片,其创建格式为:
注: length不可以省略,capacity可以省略;capacity省略,则默认和length值相同。
直接创建切片的方式有5种,如表2所示。
注:slice1的赋值语句,slice5、slice6、slice7、slice8赋值操作符语句是执行语句,必须在函数内部。
示例如下:
5.2 基于数组创建新切片
切片可以基于一个已经存在的数组创建。切片可以只使用数组的一部分元素或者所有元素来创建。
基于数组创建的切片,切片长度值等于所取数组的元素个数,容量值等于切片第一个元素在数组的位置距离数组最后一个元素的距离。
示例如下:
5.3 基于已知切片创建新切片
切片可以基于一个已经存在的切片创建。新切片(reslice)可以只使用已有切片(slice)中的一部分元素或者整个元素来创建。
5.3.1 新建切片和已知切片、底层数组之间的
关系
每个切片都会指向对应的底层数组。新切片基于已知切片的部分或全部元素创建,但新建片也指向底层数组,新切片中指针存储的地址为新切片第一个元素在底层数组中存储的空间位置。如图2所示,Slice_a指向底层数组Array_ori,Slice_a数据结构中的指针存储的是底层数组Array_ori中c所在的空间地址。Slice_b基于Slice_a创建,此时Slice_b也指向该底层数组Array_ori,Slice_b数据结构中的指针存储的是底层数组Array_ori中d所在的空间地址。
已知切片、新建切片的容量(capacity)等于切片中第一个元素在底层数组的位置与底层数组最后一个元素的位置距离。如图2所示,数组Array_ori的长度为11,容量也为11。切片Slice_a的长度为3,容量的计算方式为c在数组的位置距离数组最后一个元素k的距离,即为9;同理,切片Slice_b的长度为2,容量为数组元素d距离数组最后一个元素k的距离,即为8。
5.3.2 基于已知切片创建新切片的方式
基于已知切片创建新切片的操作方式如表4所示。
参考资料
[1] 许式伟,吕桂华.Go语言编程[M].北京:人民邮电出版社,2012:32.
本文完,获取更多资讯,敬请关注区块链工程师。
领取专属 10元无门槛券
私享最新 技术干货