go - 立即评估延迟调用的参数

标签 go deferred

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 的返回值将被延迟。它的参数被评估,但实际上它没有参数。

所以逻辑上是这样的:

  1. 评估延迟函数值,这需要:
      必须调用
    • def 函数,这需要:
      • 评估def 的参数,它是一个常量:"defered line"
  2. 评估延迟函数的参数;由于没有参数,此步骤已完成。

如果我们布置上述结构,这就是顺序发生的事情:

  • def 的参数进行评估:它是一个常量 "defered line"
  • def 被调用,打印 tier up 及其参数:defered line
  • def 的返回值被调用,这就是延迟的值。
  • 函数 main 输出:main
  • 函数 main 返回,因此现在调用延迟函数。延迟函数打印 clean up

关于go - 立即评估延迟调用的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54601007/

相关文章:

javascript - 如何强制 jquery $.when(...) 失败

jquery - 在 jQuery 中获得已解决的 promise 的更好方法?

go - 如何通过 Dropbox(或类似平台)跨多个平台共享 GOPATH

go - 从 vendor 目录使用 google.golang.org/grpc 时出错

go - 如何获得多对多的数据关联

jquery - 与 jquery 1 和 2 不同,jquery 3 ajax 处理程序仅在完成处理程序代码后才执行新添加的 html+js

jquery - 使用 jQuery.Deferred 避免嵌套 setTimeout 回调

python - Twisted Producer 延迟写入

go - 使用值创建结构实例

提供静态文件时出现 golang 错误