切片操作 #

一、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]

关键点:

  1. append:返回新切片,可能扩容
  2. copy:复制元素,返回复制数量
  3. 切片表达式:注意容量共享
  4. 删除:注意内存泄漏
  5. 预分配:提高性能

准备好学习切片原理了吗?让我们进入下一章!

最后更新:2026-03-26