9/11/2025

Go: slice作为函数参数的解包

 

在 Go 语言里,... 跟在 slice 后面,是 “解包(unpack)”操作,它的作用是把一个切片的元素逐个展开,作为可变参数传入函数,而不是把整个切片当作一个单独的参数。


📌 典型场景:append 追加切片

s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6}

// 如果直接 append(s1, s2) 会报错,因为 s2 是一个切片,不是单个元素
// 用 ... 解包,把 s2 的每个元素依次追加到 s1
s1 = append(s1, s2...)
fmt.Println(s1) // 输出: [1 2 3 4 5 6]

这里的 s2... 就是把 s2 展开成 4, 5, 6 三个独立的参数传给 append


📌 适用范围

... 这种解包语法只能用在函数调用的最后一个参数位置,并且该参数必须是可变参数(variadic parameter),例如:

func sum(nums ...int) int {
    total := 0
    for _, v := range nums {
        total += v
    }
    return total
}

arr := []int{1, 2, 3}
fmt.Println(sum(arr...)) // 等价于 sum(1, 2, 3)


在 Go 里,严格意义上并没有一个和 ... 解包对称的“打包/合并”运算符。
所谓“合并”切片,通常是通过 appendcopy 等函数来实现的,而不是用某个单独的语法符号。


🔹 常见的“合并”方式

1. 用 append 合并两个或多个切片

a := []int{1, 2, 3}
b := []int{4, 5, 6}
c := []int{7, 8}

// 合并 a 和 b
a = append(a, b...) // b... 是解包,把 b 的元素追加到 a

// 再合并 c
a = append(a, c...)
fmt.Println(a) // [1 2 3 4 5 6 7 8]

这里虽然用到了 ...,但它的作用是解包参数,合并的动作是由 append 完成的。


2. 用 copy 先分配好目标切片,再拷贝

a := []int{1, 2, 3}
b := []int{4, 5, 6}

merged := make([]int, len(a)+len(b))
copy(merged, a)
copy(merged[len(a):], b)

fmt.Println(merged) // [1 2 3 4 5 6]

这种方式在需要精确控制内存分配时更高效,因为只分配一次底层数组。


3. 多个切片一次性合并

a := []int{1, 2}
b := []int{3, 4}
c := []int{5, 6}

merged := append(append(a, b...), c...)
fmt.Println(merged) // [1 2 3 4 5 6]

Go 没有像 Python 那样的 + 运算符直接拼接切片,必须显式调用 append


在 Go 语言里,copy 是一个内置函数,专门用来将一个切片(slice)的元素复制到另一个切片。它的函数签名是:

func copy(dst, src []T) int
  • dst:目标切片(要把数据复制到这里)
  • src:源切片(数据从这里来)
  • 返回值:实际复制的元素个数(取 len(dst)len(src) 的最小值)

🔹 基本用法

a := []int{1, 2, 3}
b := make([]int, 5) // 目标切片长度为 5
n := copy(b, a)

fmt.Println(b) // [1 2 3 0 0]
fmt.Println(n) // 3

这里 copy 会把 a 的前三个元素复制到 b 的前三个位置,剩下的保持原值。


🔹 部分复制

copy 可以配合切片表达式复制一部分:

src := []int{10, 20, 30, 40, 50}
dst := make([]int, 3)

copy(dst, src[2:]) // 从 src 的第 3 个元素开始复制
fmt.Println(dst)   // [30 40 50]

🔹 特点与注意事项

  • 不会自动扩容copy 只会在 dst 已有的长度范围内复制,不会改变 dst 的长度。
  • 类型必须一致dstsrc 的元素类型必须相同。
  • 可以重叠dstsrc 可以引用同一个底层数组(甚至有重叠区域),copy 会安全处理。
  • 深浅拷贝
    • 对于基础类型元素,copy 复制的是值(相当于深拷贝元素本身)。
    • 对于引用类型元素(如切片、map、指针、结构体中含指针),copy 复制的是引用地址(浅拷贝)。


Go: slice作为函数参数的解包

  在 Go 语言里, ... 跟在 slice 后面 ,是 “解包(unpack)”操作 ,它的作用是 把一个切片的元素逐个展开,作为可变参数传入函数 ,而不是把整个切片当作一个单独的参数。 📌 典型场景: append 追加切片 s1 := []int{1, 2,...