go version go1.15.2 darwin/amd64
slice(切片)
// var s1 = make([]int, 3, 5) // 创建一个长度为3 容量为5的切片
// fmt.Println(s1[3]) // 试图访问下标为3的元素,panic ERROR index out of range [4] with length 3
var s2 = []int{1, 2, 3, 4, 5, 6} // 创建一个长度和容量都为6的切片
s3 := s2[1:3] // 包前不包后,得到一个长度为2(3-1)、容量为5(6-1)的切片
fmt.Println(s3) // [2 3]
var s4 = []int{1, 2, 3, 4, 5, 6} // 创建一个长度和容量都为6的切片
s5 := s4[1:3] // 长度为2(3-1)、容量为5(6-1)的切片
s5 = append(s5, 8) // 长度变为3,注意,此操作在这种条件下会影响原切片的值,此时s5的长度还没超过底层数组容量(5)
fmt.Println(s5) // [2 3 8]
fmt.Println(s4) // [1 2 3 8 5 6] 注意,原底层切片已经发生改变
// 我们再来多增加一个元素
s5 = append(s5, 9) // 长度变为4,注意,此操作在这种条件下会影响原切片的值,此时s5的长度还没超过底层数组容量(5)
fmt.Println(s5) // [2 3 8 9]
fmt.Println(s4) // [1 2 3 8 9 6]
// 我们再来多增加一个元素
s5 = append(s5, 10) // 长度变为5,注意,此操作在这种条件下会影响原切片的值,此时s5的长度还没超过底层数组容量(5)
fmt.Println(s5) // [2 3 8 9 10]
fmt.Println(s4) // [1 2 3 8 9 10]
// 我们再来多增加一个元素
s5 = append(s5, 11) // 长度变为6,注意,超过了底层数组的容量时,go会创自动建一个新的底层数组。此时的容量为多少呢?
fmt.Println(s5) // [2 3 8 9 10 11]
fmt.Println(s4) // [1 2 3 8 9 10] 底层数组不再变化,因为这个底层数组已经不是s5的底层数组了(由于原来容量(5)已经不够,新创建了一个底层数组)
fmt.Println(len(s5), cap(s5)) // 分别打印s5的长度和容量,会发现,容量已经变为10,变成原来的2倍了(“函数append会智能地处理底层数组的容量增长。在切片的容量小于1000个元素时,总是会成倍地增加容量。一旦元素个数超过1000,容量的增长因子会设为1.25” Excerpt From: [美] William Kennedy Brian Ketelsen Erik St. Martin. “Go语言实战.” Apple Books.)
source := []string{"Apple", "Orange", "Plum", "Banana", "Grape"}
s6 := source[2:3:4] // 长度 3-2 = 1 容量 4-2 = 2
fmt.Println(s6)
fmt.Println(len(s6), cap(s6))
s7 := source[2:3:6] // 如果尝试分配大于原来容量的最大值(3(5-2)),则panic
fmt.Println(s7) // 语言运行时错误
// s8 := source[2:3:2] // 如果尝试分配小于长度,则同样报错(编译错误)
// fmt.Println(s8) // 语言运行时错误
建议阅读: medium.com/swlh/golang… 加深理解