英文:
Go multiple assignment order of pointers and slices
问题
我需要你的帮助来回答一个问题,Go文档中说:
“赋值过程分为两个阶段。首先,按照通常的顺序对左边的索引表达式和指针间接引用(包括选择器中的隐式指针间接引用)以及右边的表达式进行求值。其次,按照从左到右的顺序进行赋值。”(赋值语句)
根据上述文本,我可以假设指针和索引表达式应该按照标准顺序一起执行,但看起来Go先执行索引,然后是指针,最后是其他所有内容。
x := []int{1}
var a *[]int
a = &x
x[0], *a, x[0] = 1, []int{1, 2}, (*a)[1]
//结果:索引超出范围 [1],长度为1的 (*a)[1]
然而,我期望 *a 将具有新的切片容量为2,但实际上并没有。
另一个例子是测试指针和切片的顺序:
x[0], *a, x[0] = 1, []int{1, 2}, 999 //结果:[1,2]
我期望在左到右的顺序中,*a 和 x 应该有一个新的切片,预期结果是 [999,2]。
为了更确定,我们可以修改之前的例子:
*a, x[0] = nil, 666 //结果:[] - 但不会引发错误
看起来Go有三个阶段:
- 执行所有的索引
- 执行所有的指针
- 执行其他所有内容
我理解得对吗?指针和切片的真实顺序是什么?
提前感谢!
英文:
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
- Carry out all indexes
- Carry out all pointers
- Carry out everything else
Am I understanding it right, what is the real order of pointers and slices?
Thanks in advance!
答案1
得分: 3
指针和切片的真实顺序是从左到右,就像文档中所说的那样。
你引用了规范中正确的部分来回答你的问题,但似乎你对使用的语言有误解。直接阅读它:
首先,左边的索引表达式和指针间接引用(包括选择器中的隐式指针间接引用)的操作数以及右边的表达式都按照通常的顺序进行求值。其次,按照从左到右的顺序进行赋值。
现在看看第一个例子:
x := []int{1}
var a *[]int
a = &x
x[0], *a, x[0] = 1, []int{1, 2}, (*a)[1]
当评估(*a)[1]
时,该行上的任何赋值都尚未执行。因此,引用部分中的“First”和“Second”这两个词。因此,它尝试索引[]int{1}[1]
,这是无效的。
对于第二个例子,你只需要理解当评估表达式x[0]
时,它对应于切片x
的第0个位置。不管在x[0]
评估之后x
是否被重新赋值,已经评估的x[0]
仍然对应于原始切片的第0个位置。
第三个例子使用了与第二个例子相同的知识。
你之前可能没有理解的微妙之处在于索引表达式和指针间接引用不产生值,它们产生的是变量。对于此目的,切片/数组元素也被视为变量,因此你可以将切片的底层数据想象为一系列相邻存储的不同变量。因此,x[0]
的索引表达式解析为内存中的某个特定变量,它不再依赖于x
的值。请记住,x
本身并不是一个切片。x
只是一个变量,可以表示某个切片,或者根本不表示任何切片,并且在x
的生命周期内可以发生变化。
英文:
> 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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论