go - golang defer语句是在return语句之前还是之后执行?

标签 go

我有一个关于golang defer的问题:golang defer语句是在return语句之前还是之后执行?

我已阅读 Defer_statements .但我没有得到答案。

我做了一个简单的测试:

func test1() (x int) {
    defer fmt.Printf("in defer: x = %d\n", x)

    x = 7
    return 9
}

func test2() (x int) {
    defer func() {
        fmt.Printf("in defer: x = %d\n", x)
    }()

    x = 7
    return 9
}

func test3() (x int) {
    x = 7
    defer fmt.Printf("in defer: x = %d\n", x)
    return 9
}

func main() {
    fmt.Println("test1")
    fmt.Printf("in main: x = %d\n", test1())
    fmt.Println("test2")
    fmt.Printf("in main: x = %d\n", test2())
    fmt.Println("test3")
    fmt.Printf("in main: x = %d\n", test3())
}

test1()中,使用Printf在defer后打印x。 在 test2() 中,使用匿名函数在 defer 后打印 x。 在test3()中,使用Printf在defer之后打印x,但是在x = 7之后defer。

但结果是:

test1
in defer: x = 0
in main: x = 9
test2
in defer: x = 9
in main: x = 9
test3
in defer: x = 7
in main: x = 9

所以,有谁能解释一下: 1. 为什么会得到这个结果?为什么test1打印0,test2打印9,test3打印7。 2. defer语句是在return之后执行还是在return之前执行?

非常感谢。

最佳答案

感谢@dev.bmax @Tranvu Xuannhat @rb16。在你的帮助下,我从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 ... 分成三个部分。

  1. 调用defer,评估函数参数的值。
  2. 执行 defer,将一个函数压入堆栈。
  3. 在 return 或 panic 之后执行堆栈中的函数。

我做了一个新的test4来解释

func test4() (x int) {
    defer func(n int) {
        fmt.Printf("in defer x as parameter: x = %d\n", n)
        fmt.Printf("in defer x after return: x = %d\n", x)
    }(x)

    x = 7
    return 9
}

在测试4中,

  1. 调用defer,评估n的值,n = x = 0,所以x作为参数是0。
  2. 执行 defer,将 func(n int)(0) 压入堆栈。
  3. return 9 之后执行 func(n int)(0), n in fmt.Printf("in defer x as parameter: x = %d\n", n) 已经求值,fmt.Printf("in defer x after return: x = %d\n", x) 中的 x 现在将被求值,x是9。

于是,得到了结果:

test4
in defer x as parameter: x = 0
in defer x after return: x = 9
in main: x = 9

关于go - golang defer语句是在return语句之前还是之后执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52718143/

相关文章:

Go构造函数类型

networking - SSH 监听器未关闭

windows - 转到异常 "signal arrived during cgo execution"

amazon-web-services - 使用非默认 VPC (aws-sdk-go) 时无法调用 ec2.AuthorizeSecurityGroupIngressInput

json - Q : golang pointer to map[string]interface{}

arrays - 如何在golang中对数组中的字符串进行打乱?

multithreading - 阅读缓存DIY书时的一个Go map线程安全问题

go - 如何用指针类型的匿名成员初始化 Go 结构?

dictionary - 如何在 go 中为 HashMap 创建复合键

file - 在 GO 中打印表格的有效方法