Simultaneous variable assignment in Go different from individual variable assignment

允我心安 提交于 2019-12-01 06:21:01

Assignment can be thought of as an "atomic" operation. That is, it's useful to think that all values on the left hand side of the = are "frozen" until all of the operations are finished.

Consider the following program:

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
}

Without this "freezing" behaviour, you would get 2 for both x and y, which is probably not what you'd expect from the code. It's also probably easier to reason about the semantics of this "freezing" behaviour than if the "cascading" approach were taken.

The simple answer is because it's all one statement and the value of y hasn't been updated to 2 at the point when x+y is evaluated. IE the expression on the right hand side is evaluated prior to any assignment. In the other case everything happens on step at a time so ofc y's value has been updated to 2 and you get four.

Interesting problem for academic purposes, terrible code in real life so please don't write anything like that in a real program.

The Go Programming Language Specification

Assignments

the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left:

one, two, three = '一', '二', '三'

The blank identifier provides a way to ignore right-hand side values in an assignment:

_ = x       // evaluate x but ignore it
x, _ = f()  // evaluate f() but ignore second result value

The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.

Tuple assignments are two phase assignment. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.

For example,

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()) 
}

Output:

2 3 1
2 3 1
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!