go中值传递无法交换变量因函数只操作副本,必须用指针传参:形参为int,调用时传&a、&b,函数内通过x、*y解引用赋值;大对象交换更需指针以避免拷贝开销。

为什么直接传值无法交换两个变量
Go 语言中函数参数是值传递,哪怕传入的是变量本身,函数内部拿到的也只是该值的一份副本。修改副本对原变量毫无影响。swap(a, b) 这种写法永远无法让调用方的 a 和 b 真正互换。
必须用指针传参才能修改原始变量
要改变调用方变量的值,得把变量的地址传进去,让函数能通过指针间接写入。关键点在于:函数参数类型必须是 *T,调用时需用 & 取地址。
- 函数定义形参为
*int(或对应类型的指针),而非int - 调用时传
&a和&b,不是a和b - 函数体内用
*x和*y解引用并赋值
func swap(x, y *int) {
*x, *y = *y, *x
}
// 使用:
a, b := 10, 20
swap(&a, &b) // 此时 a==20, b==10
交换非基本类型时指针更必要也更高效
对结构体、数组或大对象,值传递会复制整块内存,开销大;而传指针只传地址(通常 8 字节),既避免拷贝,又天然支持原地修改。即使不为交换,这也是 Go 中操作大对象的常规做法。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 交换两个
struct实例?传*MyStruct是唯一合理方式 - 交换两个长度为 10000 的
[]byte?传切片本身即可(因切片头含指针),但若想交换底层数据引用,仍可能需指针 - 误传值导致“看似交换成功”:比如在函数内打印
*x, *y是对的,但调用后原变量没变——说明漏了&
常见错误:nil 指针解引用 panic
如果传入的指针是 nil,执行 *x = ... 会直接 panic:panic: runtime error: invalid memory address or nil pointer dereference。生产代码中必须校验。
- 加判断:
if x == nil || y == nil { return } - 或者由调用方保证非 nil(如局部变量取地址永远安全)
- 注意:
new(int)返回非 nil 指针,可安全用于初始化后交换
指针交换本身很简单,但真正容易出问题的地方,往往不在交换逻辑,而在指针来源是否可靠、是否被提前释放、是否跨 goroutine 竞态访问——这些才是实际项目里更常踩的坑。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










