go语言学习笔记之slice用法

时间:2022-06-17 19:56:11


一、slice的概念:

Slices(切片)slice是概念上一个结构包含三个域:一个数组的指针、长度和容量。切片支持[]操作符来访问底层数组的元素。内置的len函数返回的切片长度。内置的的cap函数返回切片的容量。

切片是引用类型,这意味着如果你将一个切片赋值给另外一个切片,这两个切片将引用同一个底层数组。

二、如何创建slice

创建切片可用以下两种方法:

(1)直接创建:

s := make([]int, 10)

创建了名为s 的,有10个元素(长度等于10)的整数类型切片

如果创建后没有给slice赋值,那么slice的值为创建类型的默认值,如:

packagemain

import"fmt"

funcmain(){

 s:=make([]int,10)

 fmt.Println(s)

}

//output

//[0000000000]


s := []int{1,2,3,4,5}

创建了名为s 有5个元素的整数类型切片,并为每个元素赋值分别为1,2,3,4,5

(2)间接建立:

先建数组a 再用数组创建切片s

var a [10]int

s := a[1:5] //a[1],a[2],a[3],a[4]

创建了名为s 长度为4 容量为10 的整数类型切片,即len(s)等于4,cap(s)等于10 (效果与使用make([]int,4, 10)相似)

切片s 指向数组a[1],a[2],a[3],a[4]

当数组a 的值改变,切片s 的值也会变,因为切片s 引用数组a

(如果多个切片指向同一个数组,当这个底层数组值改变时,指向它的多个切片的值也会变)

 

也可以重新指定:

s = a[0:8]  //s 指向数组 a[0]至 a[7]

s = s[2:5]  //s 指向原切片的s[2],s[3],s[4]三个元素。

            //用[x:y]时总会指向x 至 y -1 的元素

            //当x为首个元素 或y为最后一个元素时可以省略不写

package main

import "fmt"

func main() {

         vara = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}

         s:= a[1:5]    //表示取a数组中啊a[1]到a[4]的元素值

         fmt.Println(s)//output:  [2 3 4 5]

         a[2]= 21

         fmt.Println(s)//output:[2 21 4 5] ,说明切片s和数组a指向同一内存空间

}

//output:

//[2 3 4 5]

//[2 21 4 5]


增加元素:

用append函数可增加切片的长度

s := []int{1,2,3}    //建切片s

s = append(s, 4, 5)    //当追加的是值时(可以是1个或多个)

            //它为切片s 增加两个元素,并赋值为4 和5 

也可以为切片追加切片

a := []int{6, 7}     //建切片a

s = append(s,a...)    //当追加的是切片时后面要有三个点

            //为切片s 追加切片a得出s 等于[1,2,3,4,5,6,7]

s = append(s[2:5],a...)  //得出s 等于[3,4,5,6,7]

当追加后的元素个数大于本切片的容量时,函数append会为

原来的切片s 重新分配空间,所以s 不会引用原来的数组或被追加的数组

若没有...就会报错误而无法工作;这是追加值与追加切片的不同

package main

import "fmt"

func main() {

         s:= []int{1, 2, 3} //建切片s

         s= append(s, 4, 5) //当追加的是值时(可以是1个或多个)

         fmt.Println(s)

         a:= []int{6, 7}    //建切片a

         s= append(s, a...) //当追加的是切片时后面要有三个点

         fmt.Println(s)

         s= append(s[2:5], a...) //得出s 等于[3,4,5,6,7]

         fmt.Println(s)

 

}

//output

//[1 2 3 4 5]

//[1 2 3 4 5 6 7]

//[3 4 5 6 7]


还有函数copy

copy函数用于从一个数组或切片中复制 数据到另一个切片中

n1 := copy(s, a[x:y])

把数组或切片a 复制到s 中,并反回被复制的元素个数给n1

a 可以是数组或切片,但s 只能是切片

被复制的是数组元素的值而不是引用

被复制的元素个数为len(a[x:y]) 和len(s)中较少的一个

例:

var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}

var s = make([]int, 6)

n1 := copy(s, a[:])        //说明:把a 全部的值 复制到s 中

n2 := copy(s, s[2:])       //说明:把指定范围的值复制到s 的开始位置

n3 := copy(s[4:6], a[6:8])  //说明:把指定范围的值复制到s的指定位置

package main

 

import "fmt"

 

func main() {

         vara = [...]int{0, 1, 2, 3, 4, 5, 6, 7}

         vars = make([]int, 6)

         n1:= copy(s, a[:])  //说明:把a 全部的值 复制到s 中

         fmt.Println(n1)      //赋值个数

         fmt.Println(s)       //赋值后的结果

         n2:= copy(s, s[2:]) //说明:把指定范围的值复制到s 的开始位置

         fmt.Println(n2)

         fmt.Println(s)

         n3:= copy(s[4:6], a[6:8]) //说明:把指定范围的值复制到s 的指定位置

         fmt.Println(n3)

         fmt.Println(s)

}

 

//output:

//6

//[0 1 2 3 4 5]

//4

//[2 3 4 5 4 5]

//2

//[2 3 4 5 6 7]

三、注意:

slice是一个指针而不是值。

指针比值可就小多了,因此,我们将slice作为函数参数传递比将

array作为函数参数传递会更有性能。

slice是一个指针,它指向的是一个array机构,它有两个基本函数

len和cap。 

看下面的图示:

go语言学习笔记之slice用法

slice是一个带有point(指向数组的指针),Len(数组中实际有值的个数),Cap(数组的容量)

比如上面的这个slice,它指向的数组是[3]int,其中的前两个有值,第三个为空

那么

len(slic) = 2

cap(slic) = 3

append函数就理解为往slice中加入一个值,如果未达到容量(len<cap)那么就直接往数组中加值,如果达到容量(len = cap)那么就增加一个新的元素空间,将值放在里面