[英]What is the result of a single variable expression evaluation
Running the following snippet of Go code one can realize that function foo
receives the value of the first argument actually set while evaluating the second argument of the function.运行以下 Go 代码片段,可以发现 function
foo
在评估 function 的第二个参数时接收到实际设置的第一个参数的值。 This behavior might look counterintuitive so that we need to prove this to be a part of language spec, not something implementation-specific.这种行为可能看起来违反直觉,因此我们需要证明这是语言规范的一部分,而不是特定于实现的东西。
package main
import (
"fmt"
)
func setVal(s *int, v int) int {
old := *s
*s = v
return old
}
func foo(s int, p int) {
fmt.Printf("s = %d, p = %d\n", s, p)
}
func main() {
var s int
foo(s, setVal(&s, 99))
}
Programm outputs s = 99, p = 0
, which means a modified value of variable s
has been passed to the function.程序输出
s = 99, p = 0
,这意味着变量s
的修改值已传递给 function。
Here is what the Go spec says regarding the case.这是 Go 规范关于此案的内容。
In a function call , ...arguments must be single-valued expressions... arguments are evaluated in the usual order.在function 调用中, ...arguments 必须是单值表达式... arguments 以通常的顺序计算。 After they are evaluated, the parameters of the call are passed by value to the function... Where usual order is the lexical left-to-right order.
评估后,调用的参数按值传递给 function...其中通常的顺序是词法从左到右的顺序。
A variable is a storage location for holding a value.变量是保存值的存储位置。 ...A variable's value is retrieved by referring to the variable in an expression;
...通过引用表达式中的变量来检索变量的值; it is the most recent value assigned to the variable.
它是分配给变量的最新值。
Therefore foo(s, setVal(&s, 99))
is a function call, variable s
and function setVal()
are the single-valued expressions, and s
is evaluated first.因此
foo(s, setVal(&s, 99))
是一个 function 调用,变量s
和 function setVal()
是单值表达式,首先计算s
。 The last spec statement makes one assume the result of a variable evaluation is its value, so if that is true, function foo
should receive initial value of the variable s
.最后一个规范语句假设变量评估的结果是它的值,所以如果这是真的,function
foo
应该接收变量s
初始值。
But it in fact it appears that the function receives the value of the first argument been set at the moment of evaluating the second argument, which is a bit confusing.但实际上似乎 function 收到了在评估第二个参数时设置的第一个参数的值,这有点令人困惑。
Does that mean the evaluation order is broken or the result of a variable evaluation is not its value?这是否意味着评估顺序被破坏或变量评估的结果不是它的值?
What you "miss" from the spec is Spec: Calls:您从规范中“错过”的是Spec: 调用:
In a function call, the function value and arguments are evaluated in the usual order .
在 function 调用中, function 值和 arguments以通常的顺序进行评估。 After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.
评估后,调用的参数按值传递给 function,被调用的 function 开始执行。
Evaluating the parameters does not mean their values are read or "taken".评估参数并不意味着它们的值被读取或“获取”。 The first parameter is
s
, its evaluation is s
itself, but its value is not yet read.第一个参数是
s
,它的求值是s
本身,但它的值还没有被读取。 The second parameter is evaluated, which means setVal()
is called and will modify the value of s
.第二个参数被评估,这意味着
setVal()
被调用并将修改s
的值。
Now that we have evaluated the parameters, their values are read, so s
will have the value 99
.现在我们已经评估了参数,它们的值被读取,所以
s
的值为99
。
Evaluating s
in the example is trivial, but of course that could be a more complex expression just like the second argument.在示例中评估
s
是微不足道的,但当然这可能是一个更复杂的表达式,就像第二个参数一样。 Here's a more complex example:这是一个更复杂的例子:
s, s2 := new(int), new(int)
getFunc := func() func(s int, p int) { return foo }
first := func(a, b *int) *int { return a }
getFunc()(*first(s, s2), setVal(s, 99))
Call of the last function involves the following steps:最后一个 function 的调用涉及以下步骤:
getFunc()
is called, it's return value will be the function valuegetFunc()
,它的返回值将是 function 值first()
is called, its return value is dereferenced;first()
被调用,它的返回值被取消引用; (b) setVal()
is called, its return value will be used setVal()
被调用,它的返回值将被使用*s
and the old value of s
(value returned by setVal()
).*s
的值和s
的旧值(由setVal()
返回的值)。 This will output the same as your example, try it on the Go Playground .这将 output 与您的示例相同,请在Go Playground上尝试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.