Go multiple assignment order of pointers and slices

Viewed 62

I need your help with a question, go docs say:

"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." (Assignment statements)

From the text above I can assume that pointers and index expressions should be carried out in the standard order together, but it looks like Go carry out first indexes, then pointers, then everything else.

x := []int{1}
var a *[]int
a = &x

x[0], *a, x[0] = 1, []int{1, 2}, (*a)[1] 
//result: index out of range [1] with length 1 (*a)[1]

however, I expected then *a will have a new slice capacity of 2, but it is not.

another example is to test the order of pointers and slices:

x[0], *a, x[0] = 1, []int{1, 2}, 999 //result: [1,2]

I expected during the left-right order, *a and x should have a new slice, and the expected result is [999,2].

To be more sure we can modify the previous example to:

*a, x[0] = nil, 666 //result: [] - but not a panic

It looks like Go has Three phases

  1. Carry out all indexes
  2. Carry out all pointers
  3. Carry out everything else

Am I understanding it right, what is the real order of pointers and slices?

Thanks in advance!

1 Answers

what is the real order of pointers and slices?

Left to right, just as the docs say.

You've quoted the right section of the spec to answer your question, but it seems you misunderstand the language used. Read it plainly:

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.

Now look at the first example:

x := []int{1}
var a *[]int
a = &x

x[0], *a, x[0] = 1, []int{1, 2}, (*a)[1]

When (*a)[1] is evaluated, none of the assignments on that line are carried out yet. Hence, the words "First" and "Second" in the quoted section. So, it tries to index []int{1}[1], which is invalid.

For the second example, all you must understand is that the expression x[0] corresponds to the 0 slot of slice x when the expression is evaluated. It doesn't matter if x gets reassigned after x[0] is evaluated, the already evaluated x[0] will still correspond to the 0 slot of the original slice.

The third example uses the same knowledge as the second.

The subtlety you may have not understood before is that index expressions and pointer indirections do not yield values, they yield variables. Slice/array elements are also considered to be variables for this purpose, so you can imagine a slice's underlying data as a series of distinct variables stored back-to-back. Thus, an index expression of x[0] resolves to some specific variable in memory that no longer depends on the value of x whatsoever. Remember, x is not a slice per se. x is just a variable that can denote some slice, or no slice at all, and that can change throughout the lifetime of x.

Related