
Go 的多重赋值语句(如 x, y = y, x+y)先完整计算右侧所有表达式,再统一赋值给左侧变量,因此不会出现中间状态干扰;这使其天然支持原子性交换和斐波那契式递推。
go 的多重赋值语句(如 `x, y = y, x+y`)先**完整计算右侧所有表达式**,再统一赋值给左侧变量,因此不会出现中间状态干扰;这使其天然支持原子性交换和斐波那契式递推。
在 Go 中,多重赋值(multiple assignment)并非逐条顺序执行,而是一个两阶段原子操作:
- 第一阶段(求值阶段):从左到右依次计算右侧所有表达式,并暂存结果;
- 第二阶段(赋值阶段):从左到右将暂存结果依次写入左侧对应变量。
以问题中的代码为例:
x, y := 0, 1 x, y = y, x+y // 关键语句
执行 x, y = y, x+y 时:
- ✅ 右侧先全部求值:
y当前为1,x+y当前为0+1 = 1→ 得到临时值对(1, 1); - ✅ 再统一赋值:
x = 1,y = 1。
因此最终输出 y = 1,而非按顺序执行 x = y; y = x+y 所得的 y = 2(后者会因 x 已被修改而导致 x+y 实际计算为 1+1)。
这种设计带来两个重要优势:
? 安全的变量交换
无需临时变量即可完成原子交换:
a, b := 10, 20 a, b = b, a // 等价于:tmp = a; a = b; b = tmp fmt.Println(a, b) // 输出:20 10
? 简洁的序列递推(如斐波那契)
可一行更新相邻状态,避免冗余中间变量:
a, b := 0, 1
for i := 0; i < 5; i++ {
fmt.Print(a, " ")
a, b = b, a+b // 每次同时推进:a→b,b→a+b
}
// 输出:0 1 1 2 3⚠️ 注意事项:
- 若右侧表达式含函数调用(如
f(), g()),它们按书写顺序从左到右求值,但求值结果仍全部完成后再赋值; - 若左侧存在重复变量(如
x, x = 1, 2),语法合法,但后赋值会覆盖前赋值,属危险写法,应避免; - 指针解引用或切片索引等操作也遵循“先求值、后赋值”原则,确保行为可预测。
总之,Go 的多重赋值是其简洁性与安全性的关键设计之一——它既消除了手动引入临时变量的繁琐,又通过明确的求值时序杜绝了竞态逻辑,是编写清晰、高效 Go 代码的基础技能。

















