You need to enable JavaScript to run this app. Go语言中两种指针变量交换写法为何运行结果不同
优惠活动
大模型
产品
解决方案
定价
更多

Go语言中两种指针变量交换写法为何运行结果不同

Go语言两种指针交换实现的输出差异原理

问题复现

两段交换逻辑的代码运行结果存在明显偏差,完整可运行代码如下:

func main() {
    var a int = 10
    var b int = 20
    swap(&a, &b)
    fmt.Println(a, b) // 实际输出 20 20

    var c int = 10
    var d int = 20
    swap2(&c, &d)
    fmt.Println(c, d) // 实际输出 20 10
}

// 分步赋值版本
func swap(x, y *int) {
    *x = *y
    *y = *x
}

// 多重赋值版本
func swap2(x, y *int) {
    *x, *y = *y, *x
}

差异核心原因

差异完全来自两种赋值逻辑的执行顺序规则不同:

分步赋值的执行逻辑

分步赋值是严格串行、按行顺序即时生效的:

  • 执行*x = *y时,立刻将y指向的内存值(初始为20)写入x指向的内存,此时x指向的变量值已经从原10被覆盖为20,原10的值不再保留在x指向的地址中
  • 后续执行*y = *x时,读取的*x已经是覆盖后的20,将这个值写入y指向的内存后,两个指针指向的地址最终存储的值都是20,因此输出20 20

多重赋值的执行逻辑

根据Go语言的语法规范,多重赋值的执行严格分为两个独立阶段,和分步赋值的即时生效逻辑完全不同:

  1. 第一阶段:对赋值语句左右两侧的所有操作数统一完成求值——包括计算左侧指针的指向地址、计算右侧所有指针解引用的值,所有求值结果都会被临时暂存,这个阶段不会对任何变量的内存值做修改
  2. 第二阶段:严格按照左侧操作数的排列顺序,将暂存的右侧值依次写入对应左侧操作数对应的内存地址

对应到swap2的执行流程:

  • 第一阶段求值:拿到x的地址、y的地址;同时取出y的值20、x的值10,所有暂存信息为写入地址:[x的地址, y的地址],待写入值:[20, 10],全程不会改动x、y指向的原内存值
  • 第二阶段赋值:按顺序把20写入x的地址,把10写入y的地址

最终c的值为20,d的值为10,完成正确交换,因此输出20 10

补充说明

这种分阶段执行的多重赋值规则,是Go语言不引入显式临时变量即可完成值交换的核心设计基础,和Python、Rust等支持多重赋值的语言遵循相同的语义逻辑。


内容的提问来源于stack exchange,提问作者白觐瑄

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.07 19:24:06