考虑以下使用Go 1.8评估的Go函数(playground):
func f() (int, bool) {
i := 0
c := make(chan bool)
go func() {
time.Sleep(1 * time.Second)
i = 1
c <- true
}()
// In practice, `i` will always be 0 here.
return i, <-c // returns 1, true
}
如注释中所述,该函数似乎总是在
i
产生值之后复制c
。由于在遇到return语句后〜1s发生这种情况,所以这不是我期望的。如果返回值顺序颠倒,并且返回值被赋值替换,则行为相同。
请注意,我并不是说这种行为是错误的-只是出乎意料。实际上,这几乎总是您想要发生的事情。
因此,问题是是否可以依靠这种预期/指定的行为?
在这种情况下,receive operator上的spec部分未明确说明何时阻塞线程。
最佳答案
根据order of evaluation的规范部分,像这样的语句中的函数和接收操作从左到右进行评估:
例如,在(本地函数)分配中
y[f()], ok = g(h(), i()+x[j()], <-c), k()
函数调用和通信按f()
,h()
,i()
,j()
,<-c
,g()
和k()
的顺序进行。但是,未指定这些事件与x
的评估和索引以及y
的评估相比的顺序。但是,如强调的句子中所述,未指定变量评估的顺序。
本节提供了另一个使这一点更加清晰的示例:
a := 1
f := func() int { a++; return a }
x := []int{a, f()}
// x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified
因此,虽然行为是所需的,但遗憾的是未指定行为,因此无法依赖。