1 回答

TA贡献1806条经验 获得超8个赞
Go 规范中关于 assignments的部分告诉我们,这是
第二种形式
元组赋值。它接着说:
任务分两个阶段进行。首先,左侧的索引表达式和指针间接(包括选择器中的隐式指针间接)的操作数和右侧的表达式都按通常的顺序进行计算。其次,作业是按从左到右的顺序进行的。
因此,编译器计算second
并s
通过评估它们来进行赋值——这只是产生它们的名称,或多或少1——并且还评估右侧的表达式
通常的顺序
这意味着我们必须通过链接查看“通常的顺序”是什么意思。这使我们得到评估顺序。
这里的文字有点棘手,但这个例子很有启发性:
在(函数局部)赋值中
y[f()], ok = g(h(), i()+x[j()], <-c), k()
f()
函数调用和通信按,h()
,i()
,j()
,<-c
,g()
, 和的顺序发生k()
。然而,这些事件与评估和索引x
以及评估相比的顺序y
没有指定。
让我们将其与您自己的表达式进行比较:
second, s := s[1], append(s[0:1], s[2:]...)
我们知道append
它将在之前被调用......好吧,我们不太确定:没有进一步的(调用权)函数调用或通道调用。s
但显然它必须在被分配之前被调用。
但是,与此同时,此调用相对于“评估和索引”的顺序s[1]
并未明确指定。如果先完成,该append
操作将(可能是2 次)就地修改支持 slice 的数组s[0:1]
。
那么,显然正在发生的事情append(s[0:1], s[2:]...)
实际上是在原地修改数组。然后进行评估和索引s[1]
,修改数组。这会获取 的修改后的值s[1]
并将其复制到变量second
。
为什么在这种情况下会发生这种情况,而前两个情况却没有?
那些不会调用append
,因此不允许append
就地修改数组。
1由于在内部使用了 SSA,这些都变成了对新变量的赋值,但最终结果都是一样的。
2由append
函数决定是进行就地修改还是创建新的后备数组。但是,在这种情况下,由于我们正在缩小总长度,这显然是可能的,并且实际实现每次都会利用这一点——尽管也没有具体说明!
结论
这里要做的事情是编写一个执行提取和更新的小函数,而不是作为单行程序,并简单地允许编译器将其内联成相当快的东西。当然,这使我们希望使用泛型,因此希望使用 Go 2。
- 1 回答
- 0 关注
- 119 浏览
添加回答
举报