在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
什么是延迟的,什么是立即计算的?
最佳答案
要了解延迟和评估的工作原理,首先让我们看一下 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
的返回值是 f
的参数)。
下一步:
defer f()()
如果 f
函数返回一个函数,这是有效的。函数值将被评估(这意味着 f
将被调用!)但它的返回值将不会被调用,这将被延迟。
defer f(g())()
在这种情况下,延迟函数是 f
的返回值,因此要评估延迟函数值,必须调用 f
,并且要执行此操作 g
必须先调用。 f
的返回值将被延迟(不调用)。
回到你的例子:
defer def("defered line")()
函数值被求值,即def
的返回值,所以def
被调用。 def
的返回值将被延迟。它的参数被评估,但实际上它没有参数。
所以逻辑上是这样的:
- 评估延迟函数值,这需要:
-
必须调用
def
函数,这需要:- 评估
def
的参数,它是一个常量:"defered line"
- 评估
- 评估延迟函数的参数;由于没有参数,此步骤已完成。
如果我们布置上述结构,这就是顺序发生的事情:
- 对
def
的参数进行评估:它是一个常量"defered line"
def
被调用,打印tier up
及其参数:defered line
def
的返回值未被调用,这就是延迟的值。- 函数
main
输出:main
- 函数
main
返回,因此现在调用延迟函数。延迟函数打印clean up
关于go - 立即评估延迟调用的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54601007/