
切片(Slice)是对数组的一个连续片段的引用。它包含三个要素:
arr := [5]int{10, 20, 30, 40, 50}
// 切取索引 1 到 3 (不包含 3)
// 就像数学里的 [1, 3)
s := arr[1:3]
fmt.Println(s) // [20 30]
fmt.Println(len(s)) // 2 (只有两个元素)
fmt.Println(cap(s)) // 4 (从索引1开始,后面还有 20, 30, 40, 50,共4个坑位)
不用依赖现有的数组,直接创建一个切片。
// make(类型, 长度, 容量)
// 如果省略容量,则容量 = 长度
s := make([]int, 5, 10)
fmt.Println(len(s), cap(s)) // 5, 10
切片满了怎么办?append 会自动扩容!

append 可能会导致换房子(内存重分配)。如果原来的底层数组装不下了,Go 会悄悄换一个更大的数组,把东西搬过去,然后让切片指向新家。
s = append(s, val),更新你的房产证!
s := []int{1, 2}
fmt.Printf("地址: %p\n", s)
s = append(s, 3) // 追加一个
s = append(s, 4, 5, 6) // 追加多个
fmt.Printf("新地址: %p\n", s) // 地址可能变了!
// 追加另一个切片(注意三个点,像展开卷轴一样)
s2 := []int{100, 200}
s = append(s, s2...)
因为切片是引用,修改切片会影响原数组。如果你想彻底复制一份,互不干扰,要用 copy。
src := []int{1, 2, 3}
// 必须先分配足够的空间,否则拷不进去!
dst := make([]int, len(src))
copy(dst, src) // 把 src 里的东西拷贝到 dst
dst[0] = 999
fmt.Println(src[0]) // 1 (原件不受影响)
var s []int 是 nil 切片(没分配内存)。
s := []int{} 是空切片(分配了内存,但长度为0)。
虽然它们 len 都是 0,打印出来也都是 [],但在 JSON 序列化时,一个是 null,一个是 []。
从数组 [10, 20, 30, 40, 50] 中切出 [20, 30]。
package main
import "fmt"
func main() {
arr := [5]int{10, 20, 30, 40, 50}
// 填空:切片范围
s := arr[______]
fmt.Println(s)
}
任务: 方括号里填什么?
答案: 1:3
解析: 索引从 0 开始。20 是索引 1,30 是索引 2。Go 语言切片是“左闭右开”,所以要写到 3 (不包含 3)。