1.切片的概念
Go语言中数组的长度不可改变,但在很多应用场景中,在初始定义数组时,数组的长度并不可预知,这样的序列集合无法满足要求。Go中提供了另外一种内置类型切片(slice)
,弥补了数组的缺陷。从底层来看,切片引用了数组的对象。切片可以追加元素,在追加时可能使切片的容量增大。与数组相比,切片不需要设定长度,在[]中不用设定值,相对来说比较自由。
2.切片声明使用
2.1 通过make
var slice1 = make([]int,3) slice1[0] = 1 slice1[1] = 2 slice1[2] = 4 fmt.Printf("通过make关键字[slic1] 类型:%T 值:%v \n",slice1,slice1)
|
2.2 直接初始化
slice2 := []int{1,2,4} fmt.Printf("直接初始化使用[slic2] 类型:%T 值:%v \n",slice2,slice2)
|
2.3 通过数组截取
package main import "fmt" func main() { arr := [...]int{1,2,4,6,8,10,12,14,16} slice3 := arr[0:4] fmt.Printf("从索引0开始截取到索引为4(不包括4)[slice3] 类型:%T 值:%v \n",slice3,slice3) slice33 := arr[:4] fmt.Printf("从索引0开始截取到索引为4(不包括4)[slice33] 类型:%T 值:%v \n",slice33,slice33) slice4 := arr[5:] fmt.Printf("从索引5开始截取到最后[slice4] 类型:%T 值:%v \n",slice4,slice4) }
|
3.切片删除
3.1 删除第一个元素
package main import "fmt" func main() { slice := []int{1,2,3,4,5,6} fmt.Printf("切片slice--> 值:%v len: %d cap: %d\n",slice,len(slice),cap(slice)) slice = slice[1:] fmt.Printf("删除一个元素后--> 值:%v len: %d cap: %d\n",slice,len(slice),cap(slice)) }
|
3.2 删除最后一个元素
package main import "fmt" func main() { slice := []int{1,2,3,4,5,6} fmt.Printf("切片slice--> 值:%v len: %d cap: %d\n",slice,len(slice),cap(slice)) slice = slice[:len(slice)-1] fmt.Printf("删除一个元素后--> 值:%v len: %d cap: %d\n",slice,len(slice),cap(slice)) }
|
3.3 删除指定位置元素
package main import "fmt" func main() { slice := []int{1,2,3,4} fmt.Printf("切片slice--> 值:%v len: %d cap: %d\n",slice,len(slice),cap(slice)) index := 2 front := slice[:index] behind := slice[index+1:] slice = append(front,behind...) fmt.Printf("删除索引%d后--> 值:%v len: %d cap: %d\n",index,slice,len(slice),cap(slice)) }
|
4.len()和cap()
4.1 作用
切片的长度是切片中元素的数量。切片的容量是从创建切片的索引开始的底层数组中元素的数量。切片可以通过len()
方法获取长度,可以通过cap()
方法获取容量。数组计算cap()结果与len()相同
。
4.2 使用
package main import "fmt" func main() { slice := []int{1,2,4,6,8,10,12,14,16} fmt.Printf("切片slice, len:%d cap:%d \n",len(slice),cap(slice)) slice1 := slice[0:0] fmt.Printf("切片slice1, len:%d cap:%d \n",len(slice1),cap(slice1))
var slice2 = make([]int,4,8) slice2[1] = 1 slice2[3] = 3 fmt.Printf("切片slice2, len:%d cap:%d \n",len(slice2),cap(slice2))
arr := [...]int{1,2,4,6,8,10,12,14,16} fmt.Printf("数组arr, len:%d cap:%d \n",len(arr),cap(arr)) }
|
5.切片是引用类型
切片没有自己的任何数据。它只是底层数组的一个引用。对切片所做的任何修改都将反映在底层数组中。数组是值类型,而切片是引用类型。
5.1 函数传参
package main import "fmt" func testSlice(slice []int) { slice[0] = 100 } func main() { var slice = make([]int,4,4) slice = []int{1,2,3,4} fmt.Printf("变量slice 类型: %T 内存地址: %p 值:%v \n",slice,&slice,slice) testSlice(slice) fmt.Printf("调用函数后,变量slice 类型: %T 内存地址: %p 值:%v \n",slice,&slice,slice) }
|
5.2 多切片共享
修改切片数值,当多个切片共享相同的底层数组时,对每个元素所做的更改将在数组中反映出来。
package main import "fmt" func testSlice(slice []int) { slice[0] = 100 } func main() { var slice = make([]int, 4, 4) slice = []int{1, 2, 3, 4} fmt.Printf("变量slice 类型: %T 内存地址: %p 值:%v \n", slice, &slice, slice) sliceCopy := slice fmt.Printf("变量sliceCopy 类型: %T 内存地址: %p 值:%v \n", sliceCopy, &sliceCopy, sliceCopy) slice2 := slice[0:2] fmt.Printf("变量slice2 类型: %T 内存地址: %p 值:%v \n", slice2, &slice2, slice2) testSlice(slice) fmt.Printf("调用函数后---变量slice 类型: %T 内存地址: %p 值:%v \n", slice, &slice, slice) fmt.Printf("调用函数后---变量sliceCopy 类型: %T 内存地址: %p 值:%v \n", sliceCopy, &sliceCopy, sliceCopy) fmt.Printf("调用函数后---变量slice2 类型: %T 内存地址: %p 值:%v \n", slice2, &slice2, slice2) }
|
6.append()和copy()
6.1 作用
append()
:用于往切片中追加新元素,可以向切片里面追加一个或者多个元素,也可以追加一个切片。
copy()
: 不会建立源切片与目标切片之间的联系。也就是两个切片不存在联系,其中一个修改不影响另一个。
6.2 使用append()
package main import "fmt" func testSlice(slice []int) { slice[0] = 100 } func main() { var slice = make([]int, 0, 4)
slice1 := append(slice,1) fmt.Printf("变量slice1 --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice1,len(slice1),cap(slice1),&slice1 )
slice2 := append(slice,3,4,5) fmt.Printf("变量slice2 --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice2,len(slice2),cap(slice2),&slice2 )
newSlice := []int{1,2,3,4,5,6,7} slice3 := append(slice,newSlice[:]...) fmt.Printf("变量slice3 --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice3,len(slice3),cap(slice3),&slice3 )
testSlice(slice1) fmt.Printf("调用函数后-变量slice1 --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice1,len(slice1),cap(slice1),&slice1 ) fmt.Printf("调用函数后-变量slice2 --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice2,len(slice2),cap(slice2),&slice2 ) fmt.Printf("调用函数后-变量slice3 --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice3,len(slice3),cap(slice3),&slice3 ) }
|
append()会改变切片所引用的数组的内容,从而影响到引用同一数组的其他切片。当使用append()
追加元素到切片时,如果容量不够(也就是(cap-len) == 0),Go就会创建一个新的内存地址来储存元素。
6.3 使用copy()
package main import "fmt" func main() { slice := []int{1,2,3,4} fmt.Printf("变量slice --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice,len(slice),cap(slice),&slice )
copySlice := make([]int,8)
count := copy(copySlice,slice) fmt.Printf("复制的数量: %d \n",count) fmt.Printf("变量copySlice --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", copySlice,len(copySlice),cap(copySlice),©Slice )
copySlice[0] = 100 fmt.Printf("修改后-->变量slice --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", slice,len(slice),cap(slice),&slice ) fmt.Printf("修改后-->变量copySlice --- 值: %v 长度(len):%d 容量(cap): %d 地址: %p \n", copySlice,len(copySlice),cap(copySlice),©Slice ) }
|