切片可以简单的理解为可以动态扩展的数组。
由于数组创建后长度就不能再修改了,所以golang就定义了slice,它的长度可以扩展,我们先来看一下slice源码的结构。
type slice struct {
array unsafe.Pointer
len int
cap int
}
可以看到有一个指针,其作用还是指向一个数组,所以说,slice底层还是应用在了数组这个数据结构之上。
len是切片实际使用长度,也就是实际存储元素所占用的存储空间。
cap是总占用空间,也就是切片预先申请的一段空间的总容量。
切片的定义:
通过make函数来创建切片
package main
import "fmt"
func main() {
ints1 := make([]int, 10, 20)
fmt.Printf("切片len:%v,切片cap:%v \n",len(ints1),cap(ints1))
ints2 := make([]int, 10)
fmt.Printf("切片len:%v,切片cap:%v \n",len(ints2),cap(ints2))
}
输出结果:
切片len:10,切片cap:20
切片len:10,切片cap:10
第一个make,有三个参数,第二个指定了len的长度,第三个指定了cap的长度。
第二个make,只有两个参数,如果不指定cap,默认len和cap相等。
也可以将len指定为0,当使用slice时,会自动扩展长度。
ints3 := make([]int, 0)
mt.Printf("切片len:%v,切片cap:%v \n",len(ints3),cap(ints3))
//输出结果
切片len:0,切片cap:0
除了用make方式创建切片,还可以用已定义的数组来创建。
arr1 := [10]int{1,2,3,4,5,6}
sli1 := arr1[0:4]
fmt.Println("切片sli1:",sli1)
输出结果:
切片sli1: [1 2 3 4]
这里arr1[0:4],相当于就是从下标0开始,取4个元素,也就是取到数组的下标3的元素,0,1,2,3这4个元素,其实你可以直接用4-0=4,就知道了这个表达式要取4个元素。
截取的表达式还可以省略开头或结尾的数字,省略开头表示从开头第一个元素开始截取,省略结尾表示截取到最后一个元素,看deom
arr1 := [10]int{1,2,3,4,5,6}
sli1 := arr1[0:4]
sli2 := arr1[:4]
sli3 := arr1[0:]
fmt.Println("切片sli1:",sli1)
fmt.Println("切片sli2:",sli2)
fmt.Println("切片sli3:",sli3)
输出结果:
切片sli1: [1 2 3 4]
切片sli2: [1 2 3 4]
切片sli3: [1 2 3 4 5 6 0 0 0 0]
重点看这里:
sli2 := arr1[:4] 这是从头开始截取
sli3 := arr1[0:] 这是截取到末尾
切片支持的操作:
len()
cap()
append()
copy()
上面的demo已经演示了len()和cap()的使用。
append()表示在切片末尾追加元素。
copy()用来复制切片。
//append
sli3 = append(sli3, 77)
fmt.Println("切片sli3 append后的值:",sli3)
fmt.Printf("切片sli3 append后的len:%v,cap:%v",len(sli3),cap(sli3))
输出结果:
切片sli3 append后的值: [1 2 3 4 5 6 0 0 0 0 77]
切片sli3 append后的len:11,cap:20
这里需要注意的是,77被追加到了切片的下标为11的位置。
还要注意的是,切片的len是11,cap是20,说明切片扩容了,在golang中不同类型的扩容比例是不同的,int类型每次扩容是当前容量乘以2.
//copy
sli4 := make([]int, 20)
copy(sli4, sli3)
fmt.Println("sli4:",sli4)
fmt.Printf("%p \n",sli3)
fmt.Printf("%p \n",sli4)
输出结果:
sli4: [1 2 3 4 5 6 0 0 0 0 77 0 0 0 0 0 0 0 0 0]
0xc000098000
0xc0000980a0
我把完整demo代码贴出来。
package main
import "fmt"
/**
www.itzhimei.com
*/
func main() {
ints1 := make([]int, 10, 20)
fmt.Printf("切片len:%v,切片cap:%v \n",len(ints1),cap(ints1))
ints2 := make([]int, 10)
fmt.Printf("切片len:%v,切片cap:%v \n",len(ints2),cap(ints2))
ints3 := make([]int, 0)
fmt.Printf("切片len:%v,切片cap:%v \n",len(ints3),cap(ints3))
arr1 := [10]int{1,2,3,4,5,6}
sli1 := arr1[0:4]
sli2 := arr1[:4]
sli3 := arr1[0:]
fmt.Println("切片sli1:",sli1)
fmt.Println("切片sli2:",sli2)
fmt.Println("切片sli3:",sli3)
sli3 = append(sli3, 77)
fmt.Println("切片sli3 append后的值:",sli3)
fmt.Printf("切片sli3 append后的len:%v,cap:%v \n",len(sli3),cap(sli3))
sli4 := make([]int, 20)
copy(sli4, sli3)
fmt.Println("sli4:",sli4)
fmt.Printf("%p \n",sli3)
fmt.Printf("%p \n",sli4)
}
输出结果:
切片len:10,切片cap:20
切片len:10,切片cap:10
切片len:0,切片cap:0
切片sli1: [1 2 3 4]
切片sli2: [1 2 3 4]
切片sli3: [1 2 3 4 5 6 0 0 0 0]
切片sli3 append后的值: [1 2 3 4 5 6 0 0 0 0 77]
切片sli3 append后的len:11,cap:20
sli4: [1 2 3 4 5 6 0 0 0 0 77 0 0 0 0 0 0 0 0 0]
0xc000098000
0xc0000980a0