go语言之切片slice
1、切片的介绍
切片是对数组的抽象,是数组的视图。go语言中数组的长度是不可变的,但是切片的长度可以改变,切片可以追加元素,追加元素时,切片的容量可以会被增加。
2、申明切片
var name []int
var name1 = make([]int, 0)
name2 := make([]int, 0)
一般也通过数组进行截取来获取切片,例如
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} //长度为7的数组
fmt.Println(fmt.Sprintf("arr[2:6]=%d", arr[2:6])) //切片 2,3,4,5 左包右不包
fmt.Println(fmt.Sprintf("arr[2:]=%d", arr[2:])) //切片只给起点 2 3 4 5 6 7
fmt.Println(fmt.Sprintf("arr[:6]=%d", arr[:6])) //切片只给终点 0 1 2 3 4 5
fmt.Println(fmt.Sprintf("arr[:]=%d", arr[:])) //切片不给起点不给终点 代表所有 0 1 2 3 4 5 6 7
s2 := arr[:]
s2 = s2[:5] //切片可以被再次切片,称之为Reslice
fmt.Println(fmt.Sprintf("s2[:5]=%d", s2)) //[0 1 2 3 4]
s2 = s2[2:] //切片可以被再次切片,称之为Reslice
fmt.Println(fmt.Sprintf("s2[2:]=%d", s2)) //[2 3 4]
}
3、切片的更改
更改了切片的数据,会导致底层数组的数据也更改了,因为切片是底层数组的视图。
package main
import "fmt"
func updateSlice(s []int) {
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} //长度为7的数组
//切片是对数组的视图
fmt.Println(fmt.Sprintf("未调用updateSlice之前的arr:%d", arr))
s1 := arr[2:]
fmt.Println(fmt.Sprintf("未调用updateSlice之前的s1:%d", s1))
updateSlice(s1)
fmt.Println(fmt.Sprintf("调用了updateSlice之后的s1:%d", s1))
fmt.Println(fmt.Sprintf("调用了updateSlice之后的arr:%d", arr)) //改变了切片,底层数组也改变了
fmt.Println("----------------------------------------------")
fmt.Println(fmt.Sprintf("未调用updateSlice之前的arr:%d", arr))
s2 := arr[:]
fmt.Println(fmt.Sprintf("未调用updateSlice之前的s2:%d", s2))
updateSlice(s2)
fmt.Println(fmt.Sprintf("调用了updateSlice之后的s2:%d", s2))
fmt.Println(fmt.Sprintf("调用了updateSlice之后的arr:%d", arr)) //改变了切片,底层数组也改变了
fmt.Println("----------------------------------------------")
}
运行
4、切片的底层原理
先看一个例子
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} //长度为7的数组
fmt.Println(fmt.Sprintf("arr=:%d", arr)) //[0 1 2 3 4 5 6 7]
s3 := arr[2:6]
fmt.Println(fmt.Sprintf("s3=:%d", s3)) //[2 3 4 5]
s4 := s3[3:5]
fmt.Println(fmt.Sprintf("s4=:%d", s4)) //[5 6]
}
运行
说明
S3为[2 3 4 5]很好理解,从下标为2的位置开始截取4个元素
可是为什么S4为[5 6]呢?
S4是S3从下标为3的位置开始截取2个元素,可是下标3以后就没有了元素
原来是因为切片是底层数组的视图,S3虽然显示是[2 3 4 5] 但是它可以视察到底层数组5以后是6和7两个元素,这也是为什么能S4能获取6的原因
slice底层原理
①slice由ptr和len以及cap组成
②ptr是指针,指向切片的第一个元素
③len是切片的长度,从ptr开始到结束的元素个数,当下标 超过这个长度后会报下标越界的错误
④cap表示切片的容量,表示共可以存多少个元素,当添加元素后,如果容量不够,会自动扩容
⑤切片可以向后扩展,不可以向前扩展,扩展可以超过len的值,上面的例子很好的说明了这个情况
解释完后,我们打印上面例子的长度和容量