创建和初始化:
在64位机器上一个切片需要24字节:指针字段8字节,长度字段8字节,容量字段8字节
make和切片字面量
//创建一个字符串切片
//其长度和容量都是5个元素 (如果只指定长度,那么切片容量和长度相等)
slice := make([]string, 5)
//分别指定长度和容量
slice := make([]int, 3, 5)
使用切片字面量
//不指定[]运算符中的值,初始的长度和容量会基于初始化时提供的元素个数确定
//注:[]中指定了值就是创建数组,不指定就是创建切片
slice := []string{"Red", "Blue", "Green"}
slice := []int{10, 20, 30}
nil和空切片
//创建nil整型切片
//在描述一个不存在的切片时,使用nil切片,例如函数需要返回一个切片但是发生异常时可以返回一个nil切片
var slice []int
//想表示空集合时空切片很有用,例如数据库查询返回0个查询结果时
//使用make创建空的整型切片
slice := make([]int, 0)
//使用切片字面量创建空的整型切片
slice := []int{}
使用切片:
赋值和切片
//和数组完全一样,使用[]操作符
//改变索引1的元素的值
slice[1] = 25
//创建一个长度和容量都是5的切片
slice := []int{10, 20, 30, 40, 50}
//创建一个新切片,新切片长度为2个元素,容量为4个元素
newSlice := slice[1:3]
注:现在两个切片共享一个底层数组,如果一个切片修改了底层数组的共享部分,另一个切片也能感知到
长度和容量的算法:
对底层数组的容量是k的切片slice[i:j]来说
长度:j - i
容量:k -i
理解:第一个值i表示的是新切片开始元素的索引位置,加上希望包含的元素个数就是j,上例中1 + 2 = 3。
而容量就是底层数组容量减当前索引的值
切片增长
相对于数组而言,使用切片的一个好处是可以按需增加切片的容量。append函数会处理增加长度时的所有操作细节。
append函数需要一个被操作的切片和一个要追加的值,返回一个包含修改结果的新切片
append函数总是会增加新切片的长度,但是容量不一定会变化
//创建一个长度和容量都是5的切片
slice := []int{10, 20, 30, 40, 50}
//创建一个新切片,新切片长度为2个元素,容量为4个元素
newSlice := slice[1:3]
//使用原有的容量来分配一个新元素
//将新元素赋值为60
newSlice = append(newSlice, 60)
如果底层数组的容量够用,append将可用的元素合并切片长度并赋值,会改动底层数组的元素。
如果容量不够,append会创建一个新的底层数组,该数组复制原底层数组的值
slice := []int{10, 20, 30, 40}
newSlice := append(slice, 50)
完成上述操作后newSlice拥有一个全新的底层数组,这个数组的容量是原来的两倍
append会智能处理底层数组的容量增长。在切片的容量小于1000个元素时,总是会成倍地增加容量。
一旦元素个数超过1000,容量的增长因子会设为1.25,也就是会每次增加25%的容量
创建切片时,还可以使用第三个索引选项,用来限制新切片的容量
对于slice[i:j:k],k就是i加上希望容量中包含元素的个数
长度:j - i
容量:k - i
如果在创建切片时设置切片的容量和长度一样,就可以强制让新切片的第一个append操作创建新的底层数组,与原底层数组分离
从而可以安全地进行后续修改
迭代切片
//创建一个长度和容量都是5的切片
slice := []int{10, 20, 30, 40, 50}
//迭代每个元素,并显示其值
for index, value := range slice {
fmt.Printf("Index: %d Value: %d\n", index, value)
}
注:range创建了每个元素的副本而不是直接返回对元素的引用,迭代返回的变量是一个迭代过程中根据切片依次赋值的新变量,所以value的地址总是相同的。想获取每个元素的地址可以使用slice[index]
//使用传统的for循环迭代
for index := 2; index < len(slice); index++ {
fmt.Printf("Index: %d, Value: %d\n", index, slice[index])
}
注:len函数返回切片的长度,cap函数返回切片的容量
多维切片:
创建多维切片
//创建一个整型切片的切片
slice := [][]int{{10}, {100, 200}}