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
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
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.
18.217.116.183