在 Go 中,什么时候在多值赋值中复制值?
In Go, when are values copied in multivalue assignments?
考虑以下使用 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 语句后约 1 秒发生这种情况,这不是我所期望的。
如果在 return 中颠倒值顺序并且 return 被赋值替换,则行为相同。
请注意,我并不是说这种行为是错误的——只是出乎意料。事实上,这几乎总是你想要发生的事情。
因此,问题是这种 intended/specified 行为是否值得信赖?
receive operator 的规范部分没有准确说明在这种情况下它何时会阻塞线程。
根据 order of evaluation 的规范部分,像这样的语句中的函数和接收操作是从左到右求值的:
For example, in the (function-local) assignment
y[f()], ok = g(h(), i()+x[j()], <-c), k()
the function calls and communication happen in the order f()
, h()
, i()
, j()
, <-c
, g()
, and k()
. However, the order of those events compared to the evaluation and indexing of x
and the evaluation of y
is not specified.
但是正如强调句中所说,变量求值的顺序没有规定。
本节给出了另一个例子,使这一点更加清晰:
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
因此,尽管行为符合要求,但遗憾的是未指定且不能依赖。
考虑以下使用 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 语句后约 1 秒发生这种情况,这不是我所期望的。
如果在 return 中颠倒值顺序并且 return 被赋值替换,则行为相同。
请注意,我并不是说这种行为是错误的——只是出乎意料。事实上,这几乎总是你想要发生的事情。
因此,问题是这种 intended/specified 行为是否值得信赖?
receive operator 的规范部分没有准确说明在这种情况下它何时会阻塞线程。
根据 order of evaluation 的规范部分,像这样的语句中的函数和接收操作是从左到右求值的:
For example, in the (function-local) assignment
y[f()], ok = g(h(), i()+x[j()], <-c), k()
the function calls and communication happen in the order
f()
,h()
,i()
,j()
,<-c
,g()
, andk()
. However, the order of those events compared to the evaluation and indexing ofx
and the evaluation ofy
is not specified.
但是正如强调句中所说,变量求值的顺序没有规定。
本节给出了另一个例子,使这一点更加清晰:
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
因此,尽管行为符合要求,但遗憾的是未指定且不能依赖。