2.4.1. Tuple assignment

Go supports tuple assignment, which updates the values of multiple variables simultaneously, such as

a, b := 1.2
a, b = b, a // Swap the order
Copy the code

Write it this way to find the greatest common divisor, very simple!

func gcd(x, y int) int {
    fory ! =0 {
        x, y = y, x%y
    } 
    return x
}
Copy the code

Or the Fibonacci sequence

func fib(n int) int {
    x, y := 0.1
    for i := 0; i < n; i++ {
        x, y = y, x+y
    } 
    return x
}
Copy the code

However, if the expression is too complex, you should avoid overusing tuple assignment. Because each variable assignment statement is more readable to write separately.

In addition, some expressions produce multiple values, such as calling a function with multiple return values. When such a function call occurs in an expression to the right of a tuple assignment, the number of variables on the left must match the number on the right

f, err = os.Open("foo.txt") // function call returns two values
Copy the code

Usually, such functions use an extra return value to express some type of error, such as os.Open, which returns an error of type error with an extra return value, and others, which return a Boolean value, usually called OK. The three operations we’ll see later are used similarly. If a Map lookup (§4.3), type assertion (§7.10), or channel receive (§8.4.2) occurs to the right of an assignment statement, they may all produce two results, with an additional Boolean result indicating whether the operation was successful:

v, ok = m[key] // map lookup
v, ok = x.(T) // type assertion
v, ok = <-ch // channel receiv
Copy the code

When a map lookup (§4.3), type assertion (§7.10), or channel receive (§8.4.2) occurs to the right of an assignment statement, it does not necessarily produce two results, but only one result. In cases where a value produces a result, zero is returned when a map lookup fails, a runtime panic exception is sent when a type assertion fails, and zero is returned when a channel receive fails (blocking is not considered a failure). For example:

v = m[key] // Map lookup, returns zero on failure
v = x.(T) // Type assertion, panic exception when failure occurs
v = <-ch // Pipe receives, returns zero on failure (blocking is not a failure)
_, ok = m[key] // map returns 2 values
_, ok = mm[""].false // map returns 1 value
_ = mm[""] // map returns 1 value
Copy the code

As with variable declarations, we can discard unwanted values with the underscore whitespace identifier _.

_, err = io.Copy(dst, src) // Discard the number of bytes
_, ok = x.(T) // Test only the type, ignoring the specific value
Copy the code