立即评估延迟调用的参数
The deferred call's arguments are evaluated immediately
在A Tour of Go中写着:
The deferred call's arguments are evaluated immediately, but the
function call is not executed until the surrounding function returns.
我无法理解引用的第一部分。什么叫立马?
func def(s string) func() {
fmt.Println("tier up")
fmt.Println(s)
return func(){ fmt.Println("clean up") }
}
func main() {
defer def("defered line")()
fmt.Println("main")
}
//Output:
//tier up
//defered line
//main
//clean up
https://play.golang.org/p/Av3mAEXxA4R
这里延迟什么,立即计算什么?
The deferred call's arguments are evaluated immediately, but the
function call is not executed until the surrounding function returns.
上面的句子意味着延迟的函数参数在它们被延迟的那一行被评估,但是函数将 运行 在周围的函数之后 main
returns.
A defer statement pushes a function call onto a list. The list of
saved calls is executed after the surrounding function returns. Defer
is commonly used to simplify functions that perform various clean-up
actions.
延迟函数调用在周围函数 returns 之后以后进先出的顺序执行。
延迟函数可以读取并分配给 returning 函数的命名 return 值。
上面这行写的很清楚,就是将return值传给main函数
例如:-
func c() (i int) {
defer func() { i++ }()
return 1
}
以上函数将 return 2
值而不是 1
。这就是为什么这一行
return func(){ fmt.Println("clean up") }
会在最后调用。
有关延迟的更多信息。 Please read golang blog for defer
在
defer def("defered line")()
def("defered line")
和 ()
是立即评估的延迟调用的参数。
def("defered line")
的计算结果为 func(){ fmt.Println("clean up") }
,但有副作用。
如果您将传递给 def(string)
的参数从字符串文字(在编译时计算)更改为更有趣的东西,会更清楚,例如:
func bar(s sting) string {
return s + " bar "
}
func main() {
defer def(bar(os.Args[1]) + "defered line")()
fmt.Println("main")
}
当defer def(bar(os.Args[1]) + "defered line")()
语句
被执行,def
的参数将被完全评估,
这意味着调用 bar
将第一个命令行传递给它
运行 宁您的程序时用户提供的参数,
取 bar
返回的任何内容并附加
它的字符串文字。
然后保存生成的字符串,并将传递给 def
什么时候 运行.
要了解延迟和评估的工作原理,首先让我们看一下 Spec: defer statements:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
函数值(其调用被延迟)及其参数都被评估。但是延迟函数还没有被调用。
让我们逐步迭代您的示例:
defer f("a")
在这种情况下,函数值被评估(将是 f
),并且参数被评估,这是一个常数,所以它将是 "a"
。
下一步:
defer f(g("a"))
在这种情况下,函数值被评估(将是 f
),并且参数被评估,这意味着 g
将被调用 "a"
(因为 g
的 return 值是 f
).
的参数
下一步:
defer f()()
如果 f
函数 return 是一个函数,则这是有效的。函数值将被评估(这意味着 f
将被调用!)但其 return 值将不会被调用,这将被推迟。
defer f(g())()
在这种情况下,延迟函数是 f
的 return 值,因此要评估延迟函数值,必须调用 f
,并执行此操作 g
必须先调用。 f
的 return 值将被延迟(不调用)。
回到你的例子:
defer def("defered line")()
函数值求值,是def
的return值,所以调用def
。 def
的 return 值将被推迟。它的参数被评估,但实际上它没有参数。
所以逻辑上是这样的:
- 计算延迟函数值,这需要:
必须调用 def
函数,这需要:
def
的参数被评估,它是一个常量:“defered line"
- 评估延迟函数的参数;由于没有参数,这一步就完成了。
如果我们布置上述结构,顺序会发生这种情况:
def
的参数被评估:它是一个常量 "defered line"
调用 def
打印 tier up
及其参数:defered line
-
def
的 return 值 不是 调用的,这就是延迟的。
- 函数
main
打印:main
- 函数
main
returns,所以现在调用延迟函数。延迟函数打印 clean up
在A Tour of Go中写着:
The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.
我无法理解引用的第一部分。什么叫立马?
func def(s string) func() {
fmt.Println("tier up")
fmt.Println(s)
return func(){ fmt.Println("clean up") }
}
func main() {
defer def("defered line")()
fmt.Println("main")
}
//Output:
//tier up
//defered line
//main
//clean up
https://play.golang.org/p/Av3mAEXxA4R
这里延迟什么,立即计算什么?
The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.
上面的句子意味着延迟的函数参数在它们被延迟的那一行被评估,但是函数将 运行 在周围的函数之后 main
returns.
A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns. Defer is commonly used to simplify functions that perform various clean-up actions.
延迟函数调用在周围函数 returns 之后以后进先出的顺序执行。
延迟函数可以读取并分配给 returning 函数的命名 return 值。
上面这行写的很清楚,就是将return值传给main函数
例如:-
func c() (i int) {
defer func() { i++ }()
return 1
}
以上函数将 return 2
值而不是 1
。这就是为什么这一行
return func(){ fmt.Println("clean up") }
会在最后调用。
有关延迟的更多信息。 Please read golang blog for defer
在
defer def("defered line")()
def("defered line")
和 ()
是立即评估的延迟调用的参数。
def("defered line")
的计算结果为 func(){ fmt.Println("clean up") }
,但有副作用。
如果您将传递给 def(string)
的参数从字符串文字(在编译时计算)更改为更有趣的东西,会更清楚,例如:
func bar(s sting) string {
return s + " bar "
}
func main() {
defer def(bar(os.Args[1]) + "defered line")()
fmt.Println("main")
}
当defer def(bar(os.Args[1]) + "defered line")()
语句
被执行,def
的参数将被完全评估,
这意味着调用 bar
将第一个命令行传递给它
运行 宁您的程序时用户提供的参数,
取 bar
返回的任何内容并附加
它的字符串文字。
然后保存生成的字符串,并将传递给 def
什么时候 运行.
要了解延迟和评估的工作原理,首先让我们看一下 Spec: defer statements:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
函数值(其调用被延迟)及其参数都被评估。但是延迟函数还没有被调用。
让我们逐步迭代您的示例:
defer f("a")
在这种情况下,函数值被评估(将是 f
),并且参数被评估,这是一个常数,所以它将是 "a"
。
下一步:
defer f(g("a"))
在这种情况下,函数值被评估(将是 f
),并且参数被评估,这意味着 g
将被调用 "a"
(因为 g
的 return 值是 f
).
下一步:
defer f()()
如果 f
函数 return 是一个函数,则这是有效的。函数值将被评估(这意味着 f
将被调用!)但其 return 值将不会被调用,这将被推迟。
defer f(g())()
在这种情况下,延迟函数是 f
的 return 值,因此要评估延迟函数值,必须调用 f
,并执行此操作 g
必须先调用。 f
的 return 值将被延迟(不调用)。
回到你的例子:
defer def("defered line")()
函数值求值,是def
的return值,所以调用def
。 def
的 return 值将被推迟。它的参数被评估,但实际上它没有参数。
所以逻辑上是这样的:
- 计算延迟函数值,这需要:
-
必须调用
def
函数,这需要:def
的参数被评估,它是一个常量:“defered line"
- 评估延迟函数的参数;由于没有参数,这一步就完成了。
如果我们布置上述结构,顺序会发生这种情况:
def
的参数被评估:它是一个常量"defered line"
调用 def
打印tier up
及其参数:defered line
-
def
的 return 值 不是 调用的,这就是延迟的。 - 函数
main
打印:main
- 函数
main
returns,所以现在调用延迟函数。延迟函数打印clean up