2.4 Assignments

The value held by a variable is updated by an assignment statement, which in its simplest form has a variable on the left of the = sign and an expression on the right.

x = 1                       // named variable
*p = true                   // indirect variable
person.name = "bob"         // struct field
count[x] = count[x] * scale // array or slice or map element

Each of the arithmetic and bitwise binary operators has a corresponding assignment operator allowing, for example, the last statement to be rewritten as

count[x] *= scale

which saves us from having to repeat (and re-evaluate) the expression for the variable.

Numeric variables can also be incremented and decremented by ++ and -- statements:

v := 1
v++    // same as v = v + 1; v becomes 2
v--    // same as v = v - 1; v becomes 1 again

2.4.1 Tuple Assignment

Another form of assignment, known as tuple assignment, allows several variables to be assigned at once. All of the right-hand side expressions are evaluated before any of the variables are updated, making this form most useful when some of the variables appear on both sides of the assignment, as happens, for example, when swapping the values of two variables:

x, y = y, x

a[i], a[j] = a[j], a[i]

or when computing the greatest common divisor (GCD) of two integers:

func gcd(x, y int) int {
    for y != 0 {
        x, y = y, x%y
    }
    return x
}

or when computing the n-th Fibonacci number iteratively:

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

Tuple assignment can also make a sequence of trivial assignments more compact,

i, j, k = 2, 3, 5

though as a matter of style, avoid the tuple form if the expressions are complex; a sequence of separate statements is easier to read.

Certain expressions, such as a call to a function with multiple results, produce several values. When such a call is used in an assignment statement, the left-hand side must have as many variables as the function has results.

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

Often, functions use these additional results to indicate some kind of error, either by returning an error as in the call to os.Open, or a bool, usually called ok. As we’ll see in later chapters, there are three operators that sometimes behave this way too. If a map lookup (§4.3), type assertion (§7.10), or channel receive (§8.4.2) appears in an assignment in which two results are expected, each produces an additional boolean result:

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

As with variable declarations, we can assign unwanted values to the blank identifier:

_, err = io.Copy(dst, src) // discard byte count
_, ok = x.(T)              // check type but discard result

2.4.2 Assignability

Assignment statements are an explicit form of assignment, but there are many places in a program where an assignment occurs implicitly: a function call implicitly assigns the argument values to the corresponding parameter variables; a return statement implicitly assigns the return operands to the corresponding result variables; and a literal expression for a composite type (§4.2) such as this slice:

medals := []string{"gold", "silver", "bronze"}

implicitly assigns each element, as if it had been written like this:

medals[0] = "gold"
medals[1] = "silver"
medals[2] = "bronze"

The elements of maps and channels, though not ordinary variables, are also subject to similar implicit assignments.

An assignment, explicit or implicit, is always legal if the left-hand side (the variable) and the right-hand side (the value) have the same type. More generally, the assignment is legal only if the value is assignable to the type of the variable.

The rule for assignability has cases for various types, so we’ll explain the relevant case as we introduce each new type. For the types we’ve discussed so far, the rules are simple: the types must exactly match, and nil may be assigned to any variable of interface or reference type. Constants (§3.6) have more flexible rules for assignability that avoid the need for most explicit conversions.

Whether two values may be compared with == and != is related to assignability: in any comparison, the first operand must be assignable to the type of the second operand, or vice versa. As with assignability, we’ll explain the relevant cases for comparability when we present each new type.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.116.183