我的印象是,尽管语法不同,但下面的函数a和函数b在逻辑上是等价的。但是,它们不是,我不明白它们之间的区别。
在我看来,他们都在分配:
任何人都可以帮助澄清我对多变量赋值的误解以及函数a和函数b之间的逻辑差异吗?
package main
import "fmt"
func a() (int, int, int) {
x:=1
y:=2
z:=3
z = x
x = y
y = x+y
return x, y, z
}
func b() (int, int, int) {
x:=1
y:=2
z:=3
z, x, y = x, y, x+y
return x, y, z
}
func main() {
fmt.Println(a()) // prints 2 4 1
fmt.Println(b()) // prints 2 3 1
}
答案 0 :(得分:5)
分配可以被认为是“原子”操作。也就是说,认为=
左侧的所有值都被“冻结”,直到所有操作都完成为止是有用的。
考虑以下计划:
package main
import "fmt"
func swap() (int, int) {
x := 1
y := 2
x, y = y, x
return x, y
}
func main() {
fmt.Println(swap()) // prints 2 1
}
如果没有这种“冻结”行为,2
和x
都会得到y
,可能不是你所期望的码。与“采用级联”方法相比,它也可能 更容易推理出这种“冻结”行为的语义。
答案 1 :(得分:2)
The Go Programming Language Specification
左边的操作数必须等于数量 右边的表达式,每个都必须是单值的,而且 右边的第n个表达式被赋值给第n个操作数 左:
one, two, three = '一', '二', '三'
空白标识符提供了忽略右侧值的方法 在作业中:
_ = x // evaluate x but ignore it x, _ = f() // evaluate f() but ignore second result value
转让分两个阶段进行。一,索引的操作数 表达式和指针间接(包括隐式指针) 左边的选择器中的间接和)上的表达式 权利都按照通常的顺序进行评估。第二,任务 按从左到右的顺序进行。
元组赋值是两阶段赋值。首先,左侧的索引表达式和指针间接操作(包括选择器中的隐式指针间接)的操作数和右侧的表达式都按通常的顺序进行评估。其次,分配按从左到右的顺序进行。
例如,
package main
import "fmt"
func a() (int, int, int) {
x := 1
y := 2
z := 3
// phase 1
tx := x
ty := y
// phase 2
z = tx
x = ty
y = tx + ty
return x, y, z
}
func b() (int, int, int) {
x := 1
y := 2
z := 3
z, x, y = x, y, x+y
return x, y, z
}
func main() {
fmt.Println(a())
fmt.Println(b())
}
输出:
2 3 1
2 3 1
答案 2 :(得分:2)
简单的答案是因为它是y
的所有一个陈述,2
的值在评估x+y
时尚未更新为y
。 IE在右侧的表达式在任何赋值之前进行评估。在另一种情况下,所有事情都是一步一步发生的,所以of 2
的价值已经更新为{{1}}而你得到了4。
出于学术目的的有趣问题,现实生活中的可怕代码所以请不要在真实的程序中写出类似的东西。