切片操作 #
一、append函数 #
1.1 追加元素 #
go
s := []int{1, 2, 3}
s = append(s, 4)
fmt.Println(s) // [1 2 3 4]
1.2 追加多个元素 #
go
s := []int{1, 2, 3}
s = append(s, 4, 5, 6)
fmt.Println(s) // [1 2 3 4 5 6]
1.3 追加切片 #
go
s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6}
s1 = append(s1, s2...)
fmt.Println(s1) // [1 2 3 4 5 6]
1.4 扩容机制 #
go
s := make([]int, 0, 2)
fmt.Printf("len=%d, cap=%d\n", len(s), cap(s)) // len=0, cap=2
s = append(s, 1, 2)
fmt.Printf("len=%d, cap=%d\n", len(s), cap(s)) // len=2, cap=2
s = append(s, 3) // 触发扩容
fmt.Printf("len=%d, cap=%d\n", len(s), cap(s)) // len=3, cap=4
1.5 扩容规则 #
- 容量 < 1024:翻倍
- 容量 >= 1024:增长约25%
二、copy函数 #
2.1 基本用法 #
go
src := []int{1, 2, 3}
dst := make([]int, len(src))
n := copy(dst, src)
fmt.Println(n) // 3
fmt.Println(dst) // [1 2 3]
2.2 复制部分 #
go
src := []int{1, 2, 3, 4, 5}
dst := make([]int, 3)
n := copy(dst, src[1:4])
fmt.Println(n) // 3
fmt.Println(dst) // [2 3 4]
2.3 复制到切片中间 #
go
dst := []int{1, 2, 3, 4, 5}
src := []int{10, 20}
copy(dst[1:3], src)
fmt.Println(dst) // [1 10 20 4 5]
2.4 返回值 #
copy返回复制的元素个数,取len(src)和len(dst)的较小值。
三、切片表达式 #
3.1 简单切片表达式 #
go
s := []int{1, 2, 3, 4, 5}
s1 := s[1:3] // [2 3]
s2 := s[:3] // [1 2 3]
s3 := s[2:] // [3 4 5]
s4 := s[:] // [1 2 3 4 5]
3.2 完整切片表达式 #
s[low:high:max],限制容量为max-low:
go
s := []int{1, 2, 3, 4, 5}
s1 := s[1:3:3]
fmt.Println(len(s1)) // 2
fmt.Println(cap(s1)) // 2(限制容量)
3.3 切片表达式越界 #
go
s := []int{1, 2, 3, 4, 5}
s1 := s[1:6] // panic: slice bounds out of range
四、删除元素 #
4.1 删除指定索引 #
go
s := []int{1, 2, 3, 4, 5}
i := 2 // 删除索引2
s = append(s[:i], s[i+1:]...)
fmt.Println(s) // [1 2 4 5]
4.2 删除首元素 #
go
s := []int{1, 2, 3, 4, 5}
s = s[1:]
fmt.Println(s) // [2 3 4 5]
4.3 删除尾元素 #
go
s := []int{1, 2, 3, 4, 5}
s = s[:len(s)-1]
fmt.Println(s) // [1 2 3 4]
4.4 删除不保持顺序 #
go
func remove(s []int, i int) []int {
s[i] = s[len(s)-1]
return s[:len(s)-1]
}
s := []int{1, 2, 3, 4, 5}
s = remove(s, 1)
fmt.Println(s) // [1 5 3 4]
五、插入元素 #
5.1 在指定位置插入 #
go
func insert(s []int, i, v int) []int {
s = append(s[:i], append([]int{v}, s[i:]...)...)
return s
}
s := []int{1, 2, 3, 4, 5}
s = insert(s, 2, 10)
fmt.Println(s) // [1 2 10 3 4 5]
5.2 在开头插入 #
go
s := []int{1, 2, 3}
s = append([]int{0}, s...)
fmt.Println(s) // [0 1 2 3]
5.3 在末尾插入 #
go
s := []int{1, 2, 3}
s = append(s, 4)
fmt.Println(s) // [1 2 3 4]
六、其他操作 #
6.1 清空切片 #
go
s := []int{1, 2, 3, 4, 5}
s = s[:0]
fmt.Println(s) // []
fmt.Println(len(s)) // 0
fmt.Println(cap(s)) // 5(容量不变)
6.2 删除所有元素(释放内存) #
go
s := []int{1, 2, 3, 4, 5}
s = nil
fmt.Println(s) // []
fmt.Println(len(s)) // 0
fmt.Println(cap(s)) // 0
6.3 过滤 #
go
func filter(s []int, f func(int) bool) []int {
var result []int
for _, v := range s {
if f(v) {
result = append(result, v)
}
}
return result
}
s := []int{1, 2, 3, 4, 5}
evens := filter(s, func(n int) bool { return n%2 == 0 })
fmt.Println(evens) // [2 4]
6.4 反转 #
go
func reverse(s []int) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
s := []int{1, 2, 3, 4, 5}
reverse(s)
fmt.Println(s) // [5 4 3 2 1]
6.5 去重 #
go
func unique(s []int) []int {
seen := make(map[int]bool)
var result []int
for _, v := range s {
if !seen[v] {
seen[v] = true
result = append(result, v)
}
}
return result
}
s := []int{1, 2, 2, 3, 3, 3, 4}
fmt.Println(unique(s)) // [1 2 3 4]
七、常见陷阱 #
7.1 append可能改变底层数组 #
go
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[1:3] // [2 3]
s1 = append(s1, 6) // 可能不扩容
fmt.Println(s2) // [2 3](未改变)
s1 = append(s1, 7, 8, 9) // 扩容,新数组
fmt.Println(s2) // [2 3](仍指向旧数组)
7.2 切片共享数据 #
go
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[1:3]
s2[0] = 20
fmt.Println(s1) // [1 20 3 4 5]
7.3 删除元素内存泄漏 #
go
type Data struct {
Value int
Data []byte
}
func remove(s []*Data, i int) []*Data {
s[i] = nil // 先置nil,避免内存泄漏
return append(s[:i], s[i+1:]...)
}
八、最佳实践 #
8.1 预分配容量 #
go
s := make([]int, 0, expectedSize)
8.2 使用完整切片表达式限制容量 #
go
s := []int{1, 2, 3, 4, 5}
s1 := s[1:3:3] // 独立容量,append不影响原切片
8.3 批量操作 #
go
// 好
s = append(s, values...)
// 不好
for _, v := range values {
s = append(s, v)
}
九、总结 #
切片操作要点:
| 操作 | 方法 |
|---|---|
| 追加 | append(s, elems…) |
| 复制 | copy(dst, src) |
| 删除 | append(s[:i], s[i+1:]…) |
| 插入 | append(s[:i], append([]int{v}, s[i:]…)…) |
| 清空 | s = s[:0] |
关键点:
- append:返回新切片,可能扩容
- copy:复制元素,返回复制数量
- 切片表达式:注意容量共享
- 删除:注意内存泄漏
- 预分配:提高性能
准备好学习切片原理了吗?让我们进入下一章!
最后更新:2026-03-26