GO成神之路:深入defer(续)|Go主题月

320 阅读1分钟

在《深入defer》这篇中我们解释了defer在代码中是如何运行的,上篇文章中我们遗留了一个问题,这篇文章我们解答一下这个问题。

defer是什么时候被调用的

在使用defer的时候,我们知道defer通常是用来释放io资源的,但是如果我们在defer中做一些其它的事情呢,那么程序的运行结果可能跟我们的预期并不一致,下面通过一些例子我们来验证defer与return的执行顺序。

defer是在return之后执行的?

package main

import (
	"log"
)

func main() {
	c := test()
	log.Println("main", c)
}
func test() int {
	a:=1
	log.Println(a)
	defer func() {
		a = 2
		log.Println("defer", a)
	}()
	return a
}

# out
test 1
defer 2
main 1

这个例子中,我们在test方法中定义个变量a,并在函数的最后返回了这个a的值,在main函数中定义了变量c来接收这个值,test方法中我们使用defer栈修改了这个a的值,执行结果如上。

通过这个例子中的结果得出结论:defer是在return之后执行的

defer是在return之前执行的?

我们通过一个具名返回值来改写上面的例子:

package main

import (
	"log"
)

func main() {
	a := test()
	log.Println("main", a)
}
func test() (a int){
	a=1
	log.Println(a)
	defer func() {
		a = 2
		log.Println("defer", a)
	}()
	return a // 1
}

# out
test 1
defer 2
main 2

这个结果是不是有种被啪啪打脸的感觉呢? 如果按照defer实在return之后执行的结论,那么返回的应该是a当时的值,结果main中打印的a并不是1而是2。

defer与return到底谁先执行?

讨论的篇幅过大,令起一篇:《defer与return到底谁先执行?