上一节介绍了切片的基础知识:切片的声明、空切片、切片和数组的区别、切片和底层数组的关联、切片的创建。这一节主要介绍切片的几个操作(遍历、追加、拷贝、插入、删除),最后介绍切片作为函数参数的传递方式。
一、切片的几个操作
1.1 对切片的遍历
类似于对数组的遍历,range结合for循环可以对切片进行遍历,格式为:
示例如下:
1.2 在切片中追加元素——append函数
一个切片,可以在其尾部追加新元素或某一切片的全部元素,返回新切片。
1.2.1 基于已知切片创建新切片的方式
append()函数是内置函数,可以在切片尾部追加与切片元素类型相同的元素,追加元素格式为:
注:注意slice_1后面要有“...”
1.2.2 追加元素后的新切片的容量变化
根据切片元素个数是否为0、是否声明了容量值,追加元素后形成的新切片的容量变化不尽相同。
▷ 1.2.2.1 元素个数大于0且没有声明容量值的切片
如果一个切片slice的元素个数大于0,且没有声明该切片的容量,追加元素形成的新切片的容量变化如下:
a. 切片slice的长度和容量均等于切片的元素个数(假设为t,t>0),则:
cap(slice)=len(slice)=t
b. 对此切片追加元素,形成新切片s1:
b1. 若t<len(s1)≤2t,则:cap(s1)=2t;
b2. 若len(s1)>2t,则:cap(s1)=len(s1)或cap(s1)=len(s1)+1,此时容量值必须是偶数。
c. 再对此切片追加元素,重复步骤b。
▷ 1.2.2.1 元素个数为0且没有声明容量值的切片
如果一个切片slice仅仅声明、没有初始化,或者通过make()函数创建了长度为0、没有声明容量的新切片,追加元素形成新的切片的容量变化如下:
a. 切片仅仅声明,则此切片为空切片,则:
cap(slice)=len(slice)=0
或者用make()函数创建了长度为0、没有声明容量的新切片,则:
cap(slice)=len(slice)=0
b. 对此切片追加元素(假设追加的元素个数为t),形成的切片为s1:
cap(s1)= len(s1)=t
c. 对此切片追加元素,形成的切片为s2:
c1. 若t<len(s2)≤2t,则:cap(s2)=2t;
c2. 若len(s1)>2t,则:cap(s2)=len(s2)或cap(s2)=len(s2)+1,此时容量必须是偶数。
d. 再对此切片追加元素,重复步骤c。
▷ 1.2.2.3 声明了容量值的切片
如果一个切片slice通过make()函数完成了初始化(假设元素个数为r,r>0),也声明了容量(假设容量为t,满足t≥r),追加元素形成新的切片的容量变化如下:
a. 此切片满足:
len(slice)=r,cap(slice)=t
b. 对此切片追加元素,形成新切片s1:
b1. 若len(s1)≤t,则:cap(s1)= t;
b2. 若t<len(s2)≤2t,则:cap(s1)=2t;
b3. 若len(s1)>2t,则:cap(s1)=len(s1)或cap(s1)=len(s1)+1,此时容量必须是偶数。
c. 再对此切片追加元素,重复步骤b。
1.3 切片的拷贝——copy函数
1.3.1 切片的拷贝格式
已知两个元素类型相同的切片s1、s2,Go语言的内置函数copy()可以将s2中的元素拷贝到s1中,其格式如下:
1.3.2 拷贝分类
copy(s1,s2)首先要保证s1、s2中的元素类型相同,元素类型不同是不能完成拷贝的。另外,不一定能将s2中的所有元素全部覆盖到s1上。已知m=len(s1),n=len(s2),根据s1、s2中元素个数大小分为两类:
a. 若m≥n,则切片s2中的元素全部覆盖到切片s1中前n个元数,切片s1剩下(m-n)个元素仍然保留;
b. 若m<n,则切片s2中只有前m个元素能全部覆盖到切片s1中。
1.4 在切片中插入元素
Go语言由于没有insert函数,要实现切片的插入,即在切片slice中插入一个或多个和切片元素类型相同的元素,步骤如下:
a. 在插入前,先选择要插入的位置index;
b. 将该位置之前的所有元素截取,制成一个新切片s1;
c. 将该位置及该位置后面的所有元素截取,追加到空切片,制成新切片s2;
d. 将元素a、b、c全部添加到s1中去;
e. 再将s2中的所有元素全部添加到s1中去。
1.5 删除切片中的元素
由于Go语言没有函数可以直接删除其内部元素,要删除切片slice中一个或多个元素,操作步骤如下:
a. 在删除前,先确认要删除的元素位置index;
b. 将包含这个位置之前的所有元素截取,制成一个新切片s1;
c. 将该位置后面的所有元素截取,制成一个新切片s2;
d. 将s2中的所有元素全部添加到s1尾部中去。
二、切片作为函数参数
在数组那一章节我们介绍了数组作为函数参数的传递方式:当实参是数组本身,函数参数的传递方式是值传递;当实参是数组的地址,则形参类型必须是数组指针,函数参数的传递方式是引用传递。而切片本身的数据结构里存在一个指向底层数组的指针,切片作为函数参数,其传递方式是引用传递。在自定义函数中对切片元素修改,将实际对切片进行了修改。