第 6 章 / 共 20 章
数组与切片
固定数组、切片底层结构、make/append/copy
数组
数组长度是类型的一部分,[3]int 与 [4]int 是不同类型。传参时值拷贝,因此实际开发几乎不直接用数组。
package main
import "fmt"
func main() {
var a [3]int // [0 0 0]
b := [3]int{1, 2, 3}
c := [...]int{1, 2, 3} // 编译器推断长度
fmt.Println(a, b, c, len(c))
}切片
切片是对底层数组的引用,含指针、长度、容量。可以动态增长,是 Go 最常用的集合类型。
package main
import "fmt"
func main() {
s := []int{1, 2, 3} // 字面量
s = append(s, 4, 5)
s2 := make([]int, 3, 10) // len=3, cap=10
fmt.Println(s, len(s), cap(s))
fmt.Println(s[1:3]) // 子切片 [2 3]
fmt.Println(s2)
}append 扩容
当 cap 不够时,append 会分配新底层数组并复制。返回值必须重新赋给原切片。
package main
import "fmt"
func main() {
s := []int{1, 2, 3}
s = append(s, 4) // 必须赋值回去
fmt.Println(s, len(s), cap(s))
}copy 与共享底层数组
子切片共享底层数组,修改会互相影响。用 copy 或 append 到 nil 切片可创建独立副本。
package main
import "fmt"
func main() {
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
// 简洁写法
dst2 := append([]int(nil), src...)
src[0] = 99
fmt.Println(src, dst, dst2)
}