golang defer语句是在return语句之前还是之后执行的?
我有一个关于golang defer的问题:golang defer语句是在return语句之前还是之后执行的? 我读过。但我没有得到答案 我做了一个简单的测试:golang defer语句是在return语句之前还是之后执行的?,go,Go,我有一个关于golang defer的问题:golang defer语句是在return语句之前还是之后执行的? 我读过。但我没有得到答案 我做了一个简单的测试: 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:
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
在延迟后打印x。
在test2()
中,使用匿名函数在延迟后打印x。
在test3()
中,使用Printf
在延时后打印x,但在x=7
后进行延时
但结果是:
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.延期声明是在返回后执行还是在返回前执行
非常感谢。在第一次测试中,当包含
延迟
的行运行时,将评估参数x
的值。当x
仍然为0时,它发生在第1行
请注意,即使以后会调用fmt.Printf
,它的参数也会提前评估
在第三个测试中,x
参数的值在defer
语句运行之前设置为7。同样,这发生在实际调用fmt.Printf
之前
第二次测试有点不同。变量x
在匿名函数的范围内。它的值在函数运行时计算,测试函数返回时会发生这种情况。到那时,x
是9。我将参考以解释您的结果
问题2:返回后执行延迟
问题1:来自文档
每次执行“defer”语句时,调用的函数值和参数都会像往常一样求值并重新保存,但不会调用实际函数
- 测试1:延迟调用fmt.Println。Println计算x的值,即0(零值)。test1()在主函数中返回9
- 测试2:延迟调用func(){}。当执行func(){}时(返回后),fmt.Println仅计算x。因此,x被计算为9。test2()在主函数中返回9
- 测试3:延迟调用fmt.Println。Println计算x的值,即7(x被指定为7)。test3()在主函数中返回9
func testing() err {
x, err := doSomething();
if err != nil {
return;
}
defer fmt.Println("hello")
return nil
}
所以如果err!=nil
此延迟将永远不会执行,因为程序在控件到达延迟语句之前返回
现在来回答你的问题(所有问题都将涉及延期声明)
1.在这种情况下,存储在堆栈中的语句是defer fmt.Printf(“在defer:x=%d\n,x中)
(0值为x)
defer func(){
fmt.Printf(“在延迟中:x=%d\n”,x)
}()
它依赖于x(注意,在堆栈中,defer语句是一个函数,函数的值将在函数执行时赋值)
延迟fmt.Printf(“在延迟中:x=%d\n”,x)
值为7谢谢@dev.bmax@Tranvu xunnhat@rb16。在你的帮助下,我从中找到了关键的解释 每次执行“defer”语句时,调用的函数值和参数都会像往常一样求值并重新保存,但不会调用实际函数 我们可以将延迟分为三部分
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中
func(n int)(0)
推到堆栈上func(n int)(0)
在return 9
之后,在fmt.Printf中的n(“在defer x中作为参数:x=%d\n,n)”已被计算,在fmt.Printf中的x(“在defer x中返回后:x=%d\n”,x)
现在将被计算,x是9
test4
in defer x as parameter: x = 0
in defer x after return: x = 9
in main: x = 9
试试这个代码
go run test.go
1
[2]
test_defer return 1,因此在返回后执行defer
go run test.go
1
[2]