关于交换和元组分配的基本查询

If I want to swap the values of two variables in go, I would do

func swap(xPtr, yPtr *int) {
    dummy := *xPtr                                                           
    *xPtr = *yPtr                                                            
    *yPtr = *xPtr                                                            
}

However, the cleanest solution is *xPtr, *yPtr = *yPtr, *xPtr. Why this has different effect than computing

*xPtr = *yPtr                                                            
*yPtr = *xPtr

In other words, from pure syntax I understand that if *xPtr=1, *yPtr=2, then both must be modified to 2, and not to 2, 1 as *xPtr, *yPtr = *yPtr, *xPtr actually does.

In Go, to swap simply write:

*xPtr, *yPtr = *yPtr, *xPtr

The Go Programming Language Specification

Assignments

A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right hand operand is a single multi-valued expression such as a function call, a channel or map operation, or a type assertion. The number of operands on the left hand side must match the number of values.

In the second form, 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 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.


The assignment proceeds in two phases. First, the operands of pointer indirections 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, swapping to and fro:

package main

import "fmt"

func main() {
    xPtr, yPtr := new(int), new(int)
    *xPtr, *yPtr = 1, 2
    fmt.Println(*xPtr, *yPtr)

    // Swap - idiomatic Go
    *xPtr, *yPtr = *yPtr, *xPtr
    fmt.Println(*xPtr, *yPtr)

    // is equivalent to

    // RHS - evaluate
    ty := *yPtr
    tx := *xPtr
    // LHS - assign
    *xPtr = ty
    *yPtr = tx
    fmt.Println(*xPtr, *yPtr)

    // is equivalent to

    // Optimized
    t := *xPtr
    *xPtr = *yPtr
    *yPtr = t
    fmt.Println(*xPtr, *yPtr)

    // is not equivalent to

    // Error: No swap
    *xPtr = *yPtr
    *yPtr = *xPtr
    fmt.Println(*xPtr, *yPtr)
}

Playground: https://play.golang.org/p/Ph4Dsc_jsJJ

Output:

1 2
2 1
1 2
2 1
1 1