切片
切片是动态分配大小的连续空间,与数组不一样的是,数组是固定连续空间。
切片(slice)是变长的同类型元素的序列,切片主要用于引用数组,提供了访问数组连续部分或全部元素的功能,切片可以理解成数组的一个子集,是一个动态的数组。
切片由指向数组的指针、长度和容量三个部分组成:长度为当前切片元素的数目,容量为当前切片可以容纳最多的元素数目。
可以使用内置的len()函数返回当前切片的长度,cap()函数返回当前切片的容量。
访问切片元素和数组一样,也可以通过索引下标。 0《=长度《=容量
1,从数组或者切片声明中声明切片。
var 切片变量名 []Type
未初始化切片默认是nil,长度和容量都是0。
package main import "fmt" func main(){ //a := [4]int{1,2,3,4} var slice1 []int fmt.Printf("len: %d ,cap:%d\n",len(slice1),cap(slice1)) if slice1 == nil { fmt.Println("切片为空") } }
输出结果:
len: 0 ,cap:0
切片为空
2,初始化语法
切片名 = 数组名[开始位置:结束位置]
说明:
(1)其中数组名,是已经定义好的数组。
(2)
开始位置:目标数组元素下标索引;
结束位置:目标数组元素长度。
如果开始位置为空,则默认使用0;如果结束位置为空,默认设置为数组长度。这里的结束索引下标有歧义,个人理解成结束位置为目标数组的长度。
(3)也可以初始化直接定义一个新数组。
package main import "fmt" func main(){ array := [7]int{1,2,3,4,5,6,7} var slice1 []int var slice2 []int var slice3 []int slice1 = array[2:4] slice2 = array[0:0] slice3 = array[:] fmt.Printf("len: %d ,cap:%d\n",len(slice1),cap(slice1)) if slice1 == nil { fmt.Println("切片为空") } //打印整个切片 fmt.Println(slice1) fmt.Println(slice2) fmt.Println(slice3) //取切片的最后一个元素 fmt.Println(slice1[len(slice1)-1]) //取切片开始和结束索引都是0的元素 fmt.Println(slice2)
输出结果:
len: 2 ,cap:5
[3 4]
[]
[1 2 3 4 5 6 7]
4
[]
切片取值说明:
(1)取出的元素数量为:结束位置 – 开始位置;
(2)取出元素不包含结束位置对应的索引,切片最后一个元素使用 slice[len(slice)-1] 获取;
(3)当缺省开始位置时,表示从连续区域开头到指定的结束位置;
(4)当缺省结束位置时,表示从开始位置到整个连续区域末尾;
(5)两者同时缺省时,与切片本身等效;
(6)两者同时为 0 时,等效于空切片,一般用于切片复位。
案例1:1月份分别取出上旬、中旬和下旬,表示原有的切片,以及重置切片
package main import "fmt" func main(){ //定义1月份31天 var month [31]int for i:=0;i<31;i++{ month[i] = i+1 } fmt.Println(month) var ( shangxun []int = month[0:10] zhongxun []int = month[10:20] xiaxun []int = month[20:] //整个月 month1 []int = month[:] //清空切片 month2 []int = month[0:0] ) fmt.Println(shangxun) fmt.Println(zhongxun) fmt.Println(xiaxun) fmt.Println(month1) //fmt.Println(month[]:) fmt.Println(month2) //fmt.Println(month[0:0]) }
输出结果:
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[1 2 3 4 5 6 7 8 9 10]
[11 12 13 14 15 16 17 18 19 20]
[21 22 23 24 25 26 27 28 29 30 31]
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[]
3,声明切片(原始标准声明切片格式语法,一般我们是从某一个数组或者切片中生成切片)
var 变量名 []Type
package main import "fmt" func main(){ var strSlice []string //声明一个字符串切片 var numSlice []int //声明一个整型切片 var emptySlice []int = []int{} //声明一个空切片 // fmt.Println(len(strSlice),len(numSlice),len(emptySlice)) fmt.Println(strSlice,numSlice,emptySlice) if emptySlice == nil { fmt.Printf("emptySlice为空") } if emptySlice != nil { fmt.Printf("emptySlice为空") } }
输出结果:
0 0 0
[] [] []
emptySlice为空
说明:
切片是不支持比较操作,因为切片是动态分配的!切片只允许和nil做比较。
4,使用内建函数make()构造切片
可以使用go内置函数make()创建一个切片,格式:
make([]Type ,size,cap)
说明:
[]Type:切片类型
size:切片实际长度
cap:预分配切片元素最大容量。这个只是提前分配内存空间,以后大于这个值也没问题。提前分配可以降低多次分配空间造成的性能问题。
容量可以不写,此时等于长度;make()内置函数里边的参数用逗号隔开。
package main import "fmt" func main(){ array := [10]int{1,2,3,4,5,6,7,8,9,10} var slice1 []int =make([]int,7,9) var slice2 []int = make([]int,7,10) var slice3 []int = make([]int,7) slice1 = array[:10] fmt.Printf("len:%d,cap:%d\n",len(slice1),cap(slice1)) fmt.Printf("len:%d,cap:%d\n",len(slice2),cap(slice2)) fmt.Printf("len:%d,cap:%d\n",len(slice3),cap(slice3)) fmt.Println(slice1) fmt.Println(slice2) fmt.Println(slice3) }
输出结果:
len:10,cap:10
len:7,cap:10
len:7,cap:7
[1 2 3 4 5 6 7 8 9 10]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
5,只用内建函数append()为切片添加元素
使用内建函数append()可以动态的为切片添加元素。其中cap容量是根据之前切片容量的2倍进行扩充。
append()可以直接添加具体元素,也可以添加切片。
语法:
slice = append(slice,a,b,c)
或者
slice1 = append(slice1,slice2….)
ps:添加切片的时候,需要切片名字加… 进行列表添加。
package main import "fmt" func main(){ array := [10]int{1,2,3,4,5,6,7,8,9,10} slice1 := array[0:5] slice2 := array[5:] slice3 := array[0:0] //为切片slice2添加元素 slice2 =append(slice2,11,12,13) //为切片slice3添加切片 slice3 =append(slice1,slice2...) fmt.Printf("len:%d,cap:%d,%v\n",len(slice1),cap(slice1),slice1) fmt.Printf("len:%d,cap:%d,%v\n",len(slice2),cap(slice2),slice2) fmt.Printf("len:%d,cap:%d,%v\n",len(slice3),cap(slice3),slice3) }
输出结果:
len:5,cap:10,[1 2 3 4 5]
len:8,cap:10,[6 7 8 9 10 11 12 13]
len:13,cap:20,[1 2 3 4 5 6 7 8 9 10 11 12 13]
6,通过go内置函数copy()进行切片复制
格式:
copy(目标切片,原始切片)
返回成功复制的元素个数,等于两个切片中较小的长度。
ps:
(1)如果原始目标切片本身为空,则原始切片即使复制过来,目标切片依旧是空。所以需要对目标切片进行初始化。
(2)原始切片复制到目标切片以后,目标切片的所有数据都会被覆盖,但是只覆盖目标切片元素的对应的个数数量,不会等同于源切片。
package main import "fmt" func main(){ array := [10]int{1,2,3,4,5,6,7,8,9,10} slice1 := array[0:10] slice2 := array[5:10] copy(slice2,slice1) fmt.Printf("len:%d,cap:%d,slice2:%v\n",len(slice2),cap(slice2),slice2) }
输出结果:
len:5,cap:5,slice2:[1 2 3 4 5]
6,删除切片元素
go没有直接的内置函数可以删除,但是可以通过切片自身以及append()来间接实现删除元素。
案例:删除2。输出新的切片。
package main import "fmt" func main(){ array := [5]int{1,2,3,4,5} const x int =2 slice1 := array[:x] slice2 := array[x+1:] fmt.Println(slice1,slice2) slice := append(slice1, slice2...) fmt.Println(slice) 输出结果: [1 2] [4 5] [1 2 4 5]
7,切片的切片【了解】
某一个已经存在的切片,也可以声明新切片,新切片会基于已经存在的切片。 归根结底,切片的原理是不变的。
总结:
什么是切片,切片如何取值【核心:开始位置和结束位置的灵活使用】,切片的追加、复制以及删除如何实现。
转载请注明:21运维 » Go语言复合数据类型(2)–切片