文章目录
1.什么是defer?
defer是Go语言提供的一种用于注册延迟调用的机制;让函数或语句可以在当前函数执行完毕后(包括通过
return
正常结束或者panic
导致的异常结束)执行。
defer语句通常用于一些成对操作的场景:打开连接/关闭连接;加锁/释放锁;打开文件/关闭文件等。
2.defer进阶
2.1. defer的底层原理是什么
每次defer语句执行的时候,会把函数“压栈”,函数参数会被拷贝下来;当外层函数(非代码块,如一个for循环)退出时,defer函数按照定义的逆序执行;如果defer执行的函数为nil,那么会在最终调用函数的产生panic。
defer语句并不会马上执行,而是会进入一个栈,函数return
前,会按先进后出的顺序执行。也就是说最先被定义的defer
语句最后执行。先进后出的原因是后面定义的函数可能会依赖前面的资源,自然要先执行;否则,如果前面先执行,那后面函数的依赖就没有了。
defer函数定义时,对外部变量的引用是有两种方式的,分别是作为函数参数和作为闭包引用。作为函数参数,则在defer定义时就把值传递给defer,并被cache起来;作为闭包引用的话,则会在defer函数真正调用时候根据整个上下文确定当前的值。
2.2.defer命令拆解
return xxx
上面这条语句经过编译之后,变成了三条指令:
1.返回值 = xxx
2.调用defer函数
3.空的return
1,3步才是return
语句真正的命令,第2步是defer定义的语句,这里可能会操作返回值。我们来看两个个例子,试着将return
语句和defer
语句拆解到正确的顺序。
第一个例子:
func f() (r int) {
t := 5
defer func