切片(slice)
切片的底层是数组实现的,可以按需自动增长和缩小。切片是数组的引用,因此是引用类型,不支持直接比较,只能和nil比较。切片的动态增长是通过内建函数append()来实现的,这个函数可以快速且高效地增长切片,也可以通过切片再次切割,缩小每一个切片的大小。
切片不存值,底层数组存值
切片指向一个底层数组
底层数组是占用一块连续的内存空间
创建数组切片
创建两个类型分别为 int 型和 string 型的切片,并初始化
func main(){
var slice1 []int
var slice2 []string
fmt.Println(slice1,slice2)
fmt.Println(slice1 == nil) //true,没有开辟内存空间
fmt.Println(slice2 == nil) //true
//初始化
slice1 = []int{1,3,5}
slice2 = []string{"小","马","锅"}
fmt.Println(slice1,slice2)
fmt.Println(slice1 == nil) //false,初始化已分配内存空间
fmt.Println(slice2 == nil) //false
}
/*
[] []
true
true
[1 3 5] [小 马 锅]
false
false
*/
可以看到,未初始化时的切片为 [ ],即切片的零值为 [ ]。由于切片是引用类型,切片与切片之间不能直接比较,只能与nil比较。未初始化的 slice1 和 slice2 由于没有分配到内存空间,因此与nil比较的值为 true ,初始化的 slice1 和 slice2 已经分配了内存空间,因此与 nil 比较的值为 false (分配的内存空间不同)。
make()函数创建切片
func main(){
//创建长度5,容量10的切片,未被初始化
s1 := make([]int, 5,10)
fmt.Println(s1)
fmt.Printf("s1长度:%d s1容量:%d\n",len(s1),cap(s1))
//创建长度0,容量10的切片,空切片
s2 := make([]int, 0 , 10)
fmt.Println(s2)
fmt.Printf("s2长度:%d s2容量:%d\n",len(s2),cap(s2))
}
/*
[0 0 0 0 0]
s1长度:5 s1容量:10
[]
s2长度:0 s2容量:10
*/
使用切片字面量创建切片
func main(){
s1 := []int{1,2,3,5,4,20}
fmt.Println(s1)
fmt.Printf("s1长度:%d s1容量:%d\n",len(s1),cap(s1))
s2 := []string{"字","面","量"}
fmt.Println(s2)
fmt.Printf("s2长度:%d s2容量:%d\n",len(s2),cap(s2))
}
/*
[1 2 3 5 4 20]
s1长度:6 s1容量:6
[字 面 量]
s2长度:3 s2容量:3
*/
nil 切片和空切片
有时候需要声明一个值为 nil 的切片,也叫空切片;nil 切片在底层数组中包含 0 个元素,也没有分配任何的存储空间。nil 切片还可以用来表示空集合。一个 nil 切片没有底层数组,它的长度和容量都是 0 以下是创建空切片的三种方式:声明未初始化的切片、使用make函数,使用切片字面量。
func main(){
//声明未初始化的切片是空切片,值为 nil
var slice []int
fmt.Println(slice)
//使用make函数创建空的字符型切片
s1 := make([]string, 0)
fmt.Println(s1)
//使用字面量创建空的布尔型切片
s2 :