切片:动态列表
make、append、copy、len 与 cap
切片:动态列表 是 CoddyKit 上的免费 Go Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
什么是切片?
切片是对底层数组的动态大小视图。它包含三个组成部分:指向数组的指针、长度和容量。
- 切片是引用类型——多个切片可以共享同一个底层数组
- Go 中大多数类似列表的操作都使用切片,而不是数组
切片字面量与 make
使用字面量或 make 创建切片:
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5} // literal
strs := make([]string, 3) // len=3, cap=3, zero values
buf := make([]byte, 0, 64) // len=0, cap=64
fmt.Println(nums, strs, len(buf), cap(buf))
}len 与 cap
len 返回切片当前包含的元素数量。cap 返回从切片起始指针开始计算的底层数组容量。
package main
import "fmt"
func main() {
s := make([]int, 3, 8)
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 8
}append:增长切片
append 会向切片添加元素;当容量不足时,它会分配新的底层数组:
package main
import "fmt"
func main() {
s := []int{1, 2, 3}
s = append(s, 4, 5)
s = append(s, []int{6, 7, 8}...)
fmt.Println(s) // [1 2 3 4 5 6 7 8]
}切分切片
使用 [low:high] 语法创建子切片(子切片会共享底层数组):
package main
import "fmt"
func main() {
a := []int{0, 1, 2, 3, 4, 5}
b := a[1:4] // [1 2 3]
c := a[:3] // [0 1 2]
d := a[3:] // [3 4 5]
fmt.Println(b, c, d)
}copy:创建独立切片
copy 会在切片之间复制元素,并返回复制的元素数量。目标切片和源切片不共享内存:
package main
import "fmt"
func main() {
src := []int{1, 2, 3}
dst := make([]int, len(src))
n := copy(dst, src)
dst[0] = 99
fmt.Println(src, dst, n) // [1 2 3] [99 2 3] 3
}nil 切片与空切片
nil 切片没有底层数组。空切片有底层数组,但长度为 0。两者的 len == 0:
package main
import "fmt"
func main() {
var nilSlice []int
emptySlice := []int{}
fmt.Println(nilSlice == nil) // true
fmt.Println(emptySlice == nil) // false
fmt.Println(len(nilSlice), len(emptySlice)) // 0 0
nilSlice = append(nilSlice, 1) // safe!
}删除元素
Go 没有用于切片的内置删除函数。惯用做法是使用 append:
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
i := 2 // delete index 2
s = append(s[:i], s[i+1:]...)
fmt.Println(s) // [1 2 4 5]
}插入元素
通过组合使用 append 和切片操作,在位置 i 处插入元素:
package main
import "fmt"
func main() {
s := []int{1, 2, 4, 5}
i := 2
s = append(s[:i+1], s[i:]...)
s[i] = 3
fmt.Println(s) // [1 2 3 4 5]
}切片陷阱:共享底层数组
子切片会共享底层数组——在重新分配发生之前,修改一个切片会影响另一个切片:
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4}
b := a[:2] // shares backing array
b[0] = 99
fmt.Println(a) // [99 2 3 4] — a is changed!
}快速检查
append 会返回什么?
回顾:切片
要点:
- 切片 = 指针 + len + cap;切片封装了数组
- 使用
make预先分配容量 - 始终为
append的结果赋值 copy会创建相互独立的切片- 请注意子切片共享底层数组的情况
练习提示
请使用 make 创建一个包含 5 个整数的切片,追加另外三个值,然后将其复制到新切片中,并修改副本且不影响原切片。请打印两个切片。
常见问题解答
「切片:动态列表」课时是免费的吗?
是的 — 「切片:动态列表」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「切片:动态列表」这节课中我会学到什么?
make、append、copy、len 与 cap 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「切片:动态列表」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 数组:定长集合
- 切片:动态列表
- 映射:键值存储
- 使用 range 遍历集合