我对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
在延后打印x。
在test2()
中,使用匿名函数在延迟后打印x。
在test3()
中,使用Printf
在延迟后打印x,但在x = 7
之后延迟x。
但是结果是:
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.延迟陈述是在归还之后还是归还之前执行?
非常感谢。
答案 0 :(得分:2)
感谢@ dev.bmax @Tranvu Xuannhat @ rb16。在您的帮助下,我从Defer_statements找到了关键的解释。
每次执行“ defer”语句时,都会照常评估调用的函数值和参数并重新保存,但不会调用实际函数。
我们可以将defer ...
分成三部分。
我做了一个新的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
}
在test4中,
func(n int)(0)
推入堆栈。func(n int)(0)
之后执行return 9
,已评估fmt.Printf("in defer x as parameter: x = %d\n", 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
答案 1 :(得分:1)
在 first 测试中,当运行包含x
的行时,将评估参数defer
的值。当x
仍为0时,它发生在第1行。
请注意,即使稍后会调用fmt.Printf
,也会提前评估其参数。
在第三测试中,在x
语句运行之前,参数defer
的值设置为7。同样,这发生在实际调用fmt.Printf
之前。
第二测试有点不同。变量x
在匿名函数的范围内。它的值在函数运行时进行评估,这在测试函数返回时发生。到那时x
是9。
答案 2 :(得分:1)
我将参考Defer_statements来解释您的结果。
问题2:在返回后推迟执行。
问题1:来自文档
每次执行“ defer”语句时,都会照常评估调用的函数值和参数并重新保存,但不会调用实际函数。
测试1:Defer调用fmt.Println。 fmt.Println评估x的值,该值为0(零值)。 test1()在主函数中返回9。
测试2:Defer调用func(){}。 fmt.Println仅在执行func(){}时(返回之后)评估x。因此,x的值为9。test2()在主函数中返回9。
测试3:Defer调用fmt.Println。 fmt.Println评估x的值为7(x分配给7)。 test3()在主函数中返回9。
答案 3 :(得分:0)
不是在此之前还是之后,这完全取决于defer语句是否存在于堆栈中。 如果是这样(如果控件到达defer语句,则将store语句保存到堆栈中),然后在return语句之后执行。
例如-
func testing() err {
x, err := doSomething();
if err != nil {
return;
}
defer fmt.Println("hello")
return nil
}
因此,如果err != nil
永远不会执行,因为程序在控件到达defer语句之前就返回了。
现在来回答您的问题(所有内容都会提交到defer语句)
1.情况下,存储在堆栈中的语句为defer fmt.Printf("in defer: x = %d\n", x)
(x的值为零)
defer func() {
fmt.Printf("in defer: x = %d\n", x)
}()
哪个依赖于x(在堆栈中请注意defer语句是一个函数,并且函数的值将在函数执行时分配)
defer fmt.Printf("in defer: x = %d\n", x)
的值为7 答案 4 :(得分:0)
package main
import "fmt"
func deque(a *[]int) {
*a = (*a)[1:]
}
func test_defer(a* []int) int{
defer deque(a)
return (*a)[0]
}
func main() {
a := []int{1,2}
fmt.Println(test_defer(&a))
fmt.Println(a)
}
尝试此代码
go run test.go
1
[2]
test_defer返回1,因此在返回后执行延期