一、什么是切片
1.切片就是一个“动态”数组,即切片的长度是可以伸缩的。其数据结构是一个结构体,包含三个字段,指向数组的指针、长度、容量。
type slice struct {
array unsafe.Pointer //一个指向数组的指针
len int
cap int
}
2.切片的指针指向某个数组,所以它是引用类型。
3.代码验证切片是引用类型
package main
import "fmt"
//传入切片
func change(s []string) {
s[1] = "c++"
}
func main() {
lang := []string{"golang","java","php","js"}
fmt.Println(lang[1]) //java
change(lang)
fmt.Println(lang[1]) //c++
}
二、切片创建
1.申明并创建(分两步:1-声明 2-make初始化)
var s1 []int //申明
s1 = make([]int , 2) //分配内存
2.直接make()创建
var s []int = make([]int , 6)
3. 推导make创建
s := make([]int , 6)
4.从数组中截取
arr := [8]int{1,2,3,4,5,6,7,8}
s := arr[1:5]
三、nil切片和空切片
1.nil切片:声明为切片,但是没有分配内存。切片的指针是nil
注意:只有声明的切片才会产生nil切片,通过推导或数组截取的切片都是指针有指向的。
var s []int
2.空切片:切片指针指向了一个数组内存地址,但是数组是空的。 空切片有两种方式产生,如下:
s1 := []int{} //1.空切片,没有任何元素
s2 := make( []int, 0) //2.make 切片,没有任何元素
3.nil切片和空切片的本质区别就是: nil切片没有分配内存,空切片是有分配内存但底层指向的是一个空数组
四、用数组 和 切片 初始化切片
1.初始化
arr := [5]int{1, 2, 3, 4, 5} //数组
s1 := arr[:] //数组初始化切片
s2 := s1[:] //切片s1初始化切片s2
2.截取操作符 [ startIndex : endIndex ]
注意:截取中的startIndex、endIndex 指的是数组或切片的下标位置,startIndex是截取时开始的位置,endIndex是结束的位置,而不包含结束位置的元素
2.数组截取初始化切片实例
全局变量:
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} //这是一个数组
var slice0 []int = arr[start:end]
var slice1 []int = arr[:end]
var slice2 []int = arr[start:]
var slice3 []int = arr[:]
var slice4 = arr[:len(arr)-1] //去掉切片的最后一个元素
局部变量:
arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0} //这是一个数组
slice5 := arr[start:end]
slice6 := arr[:end]
slice7 := arr[start:]
slice8 := arr[:]
slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素
五、操作切片的函数 append() copy()
1.切片尾部追加元素 append()
注意:如下合并其他切片时,需要 ... 来展开切片
data := [...]int{0, 1, 2, 3, 4, 10: 0} //数组
s := data[:]
s2 := data[1:5]
s = append(s,100) //1.追加1个元素
s = append(s,200,300,400) //2.追加多个元素
s = append(s,s2...) //3.合并其他切片
2.切片的拷贝:切片分为 1-浅拷贝 2-深拷贝(copy())
2.1 浅拷贝 :源切片和目的切片共享同一底层数组空间
slice1 := make([]int, 5, 5)
slice2 := slice1
slice1[1] = 1
fmt.Println(slice1) //[0 1 0 0 0]
fmt.Println(slice2) //[0 1 0 0 0]
2.2深拷贝:源切片和目的切片各自都有彼此独立的底层数组空间,
注意:copy(s1,s2),是将源切片的内容拷贝到目的切片中,即将s2元素拷贝到s1中,如果s1长度3,s2的长度5,那么复制到s2则将前三个元素覆盖到s1的三个元素上。
slice1 := make([]int, 5, 5)
slice1[0] = 9
fmt.Println(slice1)
slice2 := make([]int, 4, 4)
slice3 := make([]int, 5, 5)
fmt.Println(slice2)
fmt.Println(slice3)
//拷贝
fmt.Println(copy(slice2, slice1)) //4
fmt.Println(copy(slice3, slice1)) //5
//独立修改
slice2[1] = 2
slice3[1] = 3
fmt.Println(slice1) //[9 0 0 0 0 0]
fmt.Println(slice2) //[9 2 0 0]
fmt.Println(slice3) //[9 3 0 0 0]
结果:
[9 0 0 0 0]
[0 0 0 0]
[0 0 0 0 0]
4
5
[9 0 0 0 0]
[9 2 0 0]
[9 3 0 0 0]