Go切片 | 青训营

93 阅读2分钟

因为数组的长度是固定的并且数组长度属于类型的一部分,所以数组有很多的局限性。我们需要一个可以改变长度数据类型以便解决某种问题,这就需要切片

切片(slice)

切片是一个拥有相同类型元素的可变长度的序列。他基于数组。

切片是引用数据类型,它包括指向底层数组的指针,切片长度,切片容量。

切片一般用于快速地操作一块数据集合。

声明

var name []T

name :切片名称

T :切片中元素的类型

例如:

var sli []int

切片的长度和容量

长度:切片中已知值的元素的个数

容量:切片中最多可以有几个元素

通过数组构造切片

切片基于数组,我们可以通过数组来构造切片

  • var sli = arr[begin : last]

0<= begin <= last <= len(arr)

数组arr中,从索引begin开始(包括begin),到索引last结束(不包括last),对应的元素组成切片,切片的长度为last-begin,容量len(arr)-begin

 

begin和last都可以省略

省略begin

a[:last] 相当于 a[0:last]

省略last

a[begin:] 相当于 a[begin:len(arr)]

都省略

a[:] 相当于 a[0:len(arr)]


  • var sli = arr[begin : last : max ]

数组arr中,从索引begin开始(包括begin),到索引last结束(不包括last),对应的元素组成切片,切片的长度为last-begin,容量max-begin

 

只能省略begin

arr[: last : max ] 相当于 arr[ 0: last: max ]

 

make()函数构造切片

sli := make([]T,size,cap)

T:切片内元素类型

size:切片长度

cap:切片容量

nil

当仅仅声明时,var name []T,没有在内存中分配内存空间,这时,name == nil,此时,name的长度和容量都为0,但是长度和容量都为0的不一定为nil,例如:

var sli = []int{}      sli != 0  len(sli) == 0  cap(sli) == 0

遍历

for循环和for range循环都可以

sli := []int{1, 3, 5}

for i := 0; i < len(sli); i++ {

    fmt.Println(sli[i])

}

for i,v := range sli {

    fmt.Println(i,v)

}

添加元素

append()

var sli = []int{0,1,2}

var sli2 = []int{10,9,8}

sli = append(sli,3)

sli = append(sli,4,5,6)

sli = append(sli,sli2)

为啥要用sli在接收:当添加元素后,切片的长度超过了底层数组的长度,就需要进行扩容,数组长度不可变,所以需要新建一个新的数组,地址不一样了,需要让指针指向新的地址

扩容

首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)。

否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap),

否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)

如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)


不同数据类型扩容原则也不一样

copy()

Go语言内建的copy()函数可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()函数的使用格式如下:

copy(destSlice, srcSlice []T)

destSlice: 目标切片

srcSlice: 数据来源切片

删除元素

Go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。 要从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...)

切片之间是不能比较的,我们不能使用==操作符来判断两个切片是否含有全部相等元素。 切片唯一合法的比较操作是和nil比较。 一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0。但是我们不能说一个长度和容量都是0的切片一定是nil