七叶笔记 » golang编程 » Go学习(十):切片

Go学习(十):切片

1.切片的概念

Go语言中数组的长度不可改变,但在很多应用场景中,在初始定义数组时,数组的长度并不可预知,这样的序列集合无法满足要求。Go中提供了另外一种内置类型 切片(slice) ,弥补了数组的缺陷。从底层来看,切片引用了数组的对象。切片可以追加元素,在追加时可能使切片的容量增大。与数组相比,切片不需要设定长度,在[]中不用设定值,相对来说比较自由。

2.切片声明使用

2.1 通过make

 //使用make()函数来创建切片
var slice1 = make([]int,3)
slice1[0] = 1
slice1[1] = 2
slice1[2] = 4
fmt.Printf("通过make关键字[slic1] 类型:%T 值:%v \n",slice1,slice1)
//  输出: 通过make关键字[slic1] 类型:[]int 值:[1 2 4] 
  

2.2 直接初始化

 // 直接初始化使用
slice2 := []int{1,2,4}
fmt.Printf("直接初始化使用[slic2] 类型:%T 值:%v \n",slice2,slice2)
// 输出: 直接初始化使用[slic2] 类型:[]int 值:[1 2 4] 
  

2.3 通过数组截取

 package main
import "fmt"
func main() {
 // 定义一个数组
 arr := [...]int{1,2,4,6,8,10,12,14,16}
 // 从索引0开始截取到索引为4(不包括4)
 slice3 := arr[0:4]
 fmt.Printf("从索引0开始截取到索引为4(不包括4)[slice3] 类型:%T 值:%v \n",slice3,slice3)
 // 索引从0开始时,0也可以省略不写
 slice33 := arr[:4]
 fmt.Printf("从索引0开始截取到索引为4(不包括4)[slice33] 类型:%T 值:%v \n",slice33,slice33)
 // 从索引4开始截取到最后
 slice4 := arr[5:]
 fmt.Printf("从索引5开始截取到最后[slice4] 类型:%T 值:%v \n",slice4,slice4)
}
/**输出
从索引0开始截取到索引为4(不包括4)[slice3] 类型:[]int 值:[1 2 4 6] 
从索引0开始截取到索引为4(不包括4)[slice33] 类型:[]int 值:[1 2 4 6] 
从索引5开始截取到最后[slice4] 类型:[]int 值:[10 12 14 16] 
*/  

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))
}
/*输出
切片slice--> 值:[1 2 3 4 5 6] len: 6 cap: 6
删除一个元素后--> 值:[2 3 4 5 6] len: 5 cap: 5
*/  

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))
}
/*输出
切片slice--> 值:[1 2 3 4 5 6] len: 6 cap: 6
删除一个元素后--> 值:[1 2 3 4 5] len: 5 cap: 6
*/  

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))
 
 // 清空切片slice赋值给slice1
 slice1 := slice[0:0]
 fmt.Printf("切片slice1, len:%d cap:%d \n",len(slice1),cap(slice1))

 // 使用make指定容量创建切片
 var slice2 = make([]int,4,8)
 slice2[1] = 1
 slice2[3] = 3
 fmt.Printf("切片slice2, len:%d cap:%d \n",len(slice2),cap(slice2))

 // 数组计算cap()结果与len()相同
 arr := [...]int{1,2,4,6,8,10,12,14,16}
 fmt.Printf("数组arr, len:%d cap:%d \n",len(arr),cap(arr))
}
/***输出:
切片slice, len:9 cap:9 
切片slice1, len:0 cap:9 
切片slice2, len:4 cap:8 
数组arr, len:9 cap:9 
*/  

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)
}
/**输出
变量slice  类型: []int 内存地址: 0xc00000c080 值:[1 2 3 4] 
调用函数后,变量slice  类型: []int 内存地址: 0xc00000c080 值:[100 2 3 4] 
*/  

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() {
 // 定义一个切片类型,长度为0,容量为4
 var slice = make([]int, 0, 4)

 //向切片中添加1个元素 (不超过容量)
 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 )
}
/**输出
变量slice1 --- 值: [1] 长度(len):1 容量(cap): 4  地址: 0xc00000c080 
变量slice2 --- 值: [3 4 5] 长度(len):3 容量(cap): 4 地址: 0xc00000c0c0 
变量slice3 --- 值: [1 2 3 4 5 6 7] 长度(len):7 容量(cap): 8 地址: 0xc00000c100 
调用函数后-变量slice1 --- 值: [100] 长度(len):1 容量(cap): 4 地址: 0xc00000c080 
调用函数后-变量slice2 --- 值: [100 4 5] 长度(len):3 容量(cap): 4 地址: 0xc00000c0c0 
调用函数后-变量slice3 --- 值: [1 2 3 4 5 6 7] 长度(len):7 容量(cap): 8 地址: 0xc00000c100 
*/  

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 )

 // 定义一个切片变量用来复制slice
 copySlice := make([]int,8)

 // 使用copy
 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 )
}
/**输出
变量slice --- 值: [1 2 3 4] 长度(len):4 容量(cap): 4  地址: 0xc00000c080 
复制的数量: 4 
变量copySlice --- 值: [1 2 3 4 0 0 0 0] 长度(len):8 容量(cap): 8  地址: 0xc00000c0c0 
修改后-->变量slice --- 值: [1 2 3 4] 长度(len):4 容量(cap): 4  地址: 0xc00000c080 
修改后-->变量copySlice --- 值: [100 2 3 4 0 0 0 0] 长度(len):8 容量(cap): 8  地址: 0xc00000c0c0 
*/  

微信搜索【猿码记】,获取最新文章信息。[得意]

相关文章