golang的数组与其它语言一样是固定长度的,需要显示定义长度,而切片则是变长的,切片为golang语言内置类型。
1.切片定义与初始化
var sli1 []int // sli1是一个空的切片对象 sli1=nil
sli2 :=[]int{} // sli2长度为0 len(sli2)==0
sli3 :=[]int{1,2,3} // sli3长度为3 初始值为1,2,3的
sli4 :=make([]int) // sli4 同sli2
sli5 :=make([]int,3) // sli5长度为3 初始值为0
sli6 :=make([]int,3,7) // sli6长度为3 cap容量=7
2.切片的遍历
sli := []int{1, 2, 3}
//普通遍历
for i := 0; i < len(sli); i++ {
fmt.Println(sli[i])
}
//range遍历 range切片的返回值有两种情况
//1 返回下标
for k := range sli {
fmt.Println(sli[k])
}
//2 返回下标+值
for k, v := range sli {
fmt.Println(k, v)
}
3.切片的len与cap
//slice是通过数组实现的,len代表当前slice有效的长度 cap代表当前slice的容量
//随着slice元素的添加 slice的len会逐渐增大,而当
sli :=make([]int,3,5)
slicopy :=sli
fmt.Println(sli) // 0 ,0 0
fmt.Println(len(sli)) // len 3
fmt.Println(cap(sli)) // cap 5
sli = append(sli,1)
fmt.Println(len(sli)) // len 4
fmt.Println(cap(sli)) // cap 5
sli = append(sli,1)
fmt.Println(len(sli)) // len 5
fmt.Println(cap(sli)) // cap 5
//此时slicopy和sli共享同一个数组
sli[0]=5
fmt.Println(slicopy[0]) // 5
//len==cap 切片内部的数组空间不足 切片会自动扩容.
sli = append(sli,1)
fmt.Println(len(sli)) // len 6
fmt.Println(cap(sli)) // cap 10
//此时slicopy和sli不再共享同一个数组
sli[0]=10
fmt.Println(slicopy[0]) // 5
4.append和copy
//切片最核心的就是可以动态增长,通过append函数添加元素
//append(slice,elems...)
sli :=[]int{}
for i:=0;i<10;i++{
sli = append(sli,i) //动态添加元素
}
//切片和数组类型使用 sliice... 相当于展开作为多参传递
sli2 :=append([]int{},sli...)
fmt.Println(sli2)
//切片赋值时由于时共享底层数组,如果想实现深拷贝则可以使用copy函数
sli3 :=make([]int,len(sli))
//copy完成之后 两个切片不再共享底层数组
copy(sli3,sli)
sli[0]=100
fmt.Println(sli[0]) //100
fmt.Println(sli3[0]) //0
5.作为函数参数
//slice作为函数参数时与数组时有不同的,golang数组作为参数,不会像其他语言一个传递指针,
//而是传递新数组,所以形参不会影响实参,而slice虽然拷贝了一个新的形参切片,
//但由于共享底层数组的,所以在初期,形参会影响实参
//数组
func main() {
data :=[3]int{1,1,1}
test1(data)
fmt.Println(data) //输出 1,1,1
}
func test1(data [3]int){
//函数中的数组和原来的不是同一个对象 改变形参不影响实参
for k :=range data{
data[k]=2
}
fmt.Println(data) //输出 2,2,2
}
//切片
func main() {
data :=[]int{1,1,1}
test1(data)
fmt.Println(data) //输出 2,2,2
}
func test1(data []int){
函数中的切片和原来的不是同一个对象 但由于共享了底层的数组,会影响到原来的切片
for k :=range data{
data[k]=2
}
fmt.Println(data) //输出 2,2,2
}
//发生扩容
func main() {
data :=[]int{1,1,1}
test1(data)
fmt.Println(data) //输出 2,2,2
test2(data)
fmt.Println(data) //输出 2,2,2
}
func test1(data []int){
函数中的切片和原来的不是同一个对象 但由于共享了底层的数组,会影响到原来的切片
for k :=range data{
data[k]=2
}
fmt.Println(data) //输出 2,2,2
}
func test2(data []int){
data =append(data,1)
data =append(data,1)
data =append(data,1)
data =append(data,1)
data =append(data,1)
//append过程发生了扩容,不再共享底层的数组 所以修改不会再影响实参了
for k :=range data{
data[k]=3
}
fmt.Println(data) //输出 3,3,3,3,3,3,3,3
}
6.切片的截取
//slice采用的是前开后闭的方式
sli :=[]int{1,2,3,4,5,6,7,8}
fmt.Println(sli) //1,2,3,4,5,6,7,8
//获得前面五个元素 前开后闭,获取 0-4范围的元素
sli1 :=sli[0:5]
fmt.Println(sli1) //1,2,3,4,5
//获得前面五个元素之后的元素 5-end
sli2 :=sli[5:len(sli)]
fmt.Println(sli2) //6,7,8
//切片类型只能和nil比较,不能相互比较
sli3 :=sli
fmt.Println(sli3==sli) //编译错误