You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang的...语法真的只是可变参数吗?修改形参为何影响实参?

Go可变参数传递:切片展开vs逐个传参的差异解析

核心原因

Go的可变参数本质是一个切片,两种传递方式的底层逻辑完全不同:

  • 切片展开传递(isle...):Go会直接将原切片的底层数组引用赋值给形参args,两者指向同一块内存空间。因此修改args的元素时,实际操作的是原切片的底层数组,原切片自然会被改变。
  • 逐个传递元素:Go会创建一个新的切片,把传递的元素逐一复制到这个新切片的底层数组中,形参args和原切片isle的底层数组完全独立,修改args不会影响原切片。

代码验证与分析

情况1:切片展开传递,原切片被修改

package main

import (
    "fmt"
)

func bubbleSort(args ...int) {
    for i := 0; i < len(args); i++ {
        for j := 0; j < len(args)-1; j++ {
            if args[j] > args[j+1] {
                args[j], args[j+1] = args[j+1], args[j]
            }
        }
    }
}

func main() {
    isle := []int{3, 6, 1, 2, 5}
    bubbleSort(isle...)

    fmt.Printf("%v\n", isle) // 输出:[1 2 3 5 6]
}

这里isle...直接把原切片的底层数组传递给args,排序操作直接修改了共享的底层数组,所以原切片isle的元素顺序被改变。

情况2:逐个传递元素,原切片不受影响

package main

import (
    "fmt"
)

func bubbleSort(args ...int) {
    for i := 0; i < len(args); i++ {
        for j := 0; j < len(args)-1; j++ {
            if args[j] > args[j+1] {
                args[j], args[j+1] = args[j+1], args[j]
            }
        }
    }
}

func main() {
    isle := []int{3, 6, 1, 2, 5}
    bubbleSort(isle[0], isle[1], isle[2], isle[3], isle[4])

    fmt.Printf("%v\n", isle) // 输出:[3 6 1 2 5]
}

逐个传递元素时,Go会新建一个切片args,将isle的元素值复制进去。排序操作只修改这个新切片的底层数组,和原切片isle无关,所以原切片内容不变。

延伸提示

如果想避免切片展开传递时修改原切片,可以在传递前创建原切片的副本:

bubbleSort(append([]int(nil), isle...)...)

这样传递给args的是副本的底层数组,排序不会影响原切片。

内容的提问来源于stack exchange,提问作者YunYaJun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:15:39