引入
不多说,上代码
package main
import "fmt"
func main() {
fmt.Println("a")
defer func() {
fmt.Println("d")
fmt.Println("e")
}()
defer fmt.Println("c")
defer fmt.Println("b")
}
运行结果
a
b
c
d
e
解析
只看上面的内容可能很难理解,但其实defer就是在函数即将返回时执行其后面的语句。
但是这任然不能解释上面内容的全部。例如为什么输出顺序是a,b,c,d,e而不是a,d,e,c,b?!
这就要多个defer的执行顺序了:最先声明defer的语句最后执行,最后声明defer的语句最先执行。
为什么是逆序?如果后面的defer语句依赖了前面的defer语句,释放前面的就必然破坏关系,是肯定不行的。
还有一个问题,defer后面还可以跟匿名函数?!
是的。这对于同时执行多个操作很有用,总不可能一个语句就一个defer吧。
还有记得声明完匿名函数后要加(),要不然就不会调用了。
用处
想象一下文件操作,是不是先打开文件才能读/写里面的内容?之后是不是还要关闭文件?
打开文件和读/写没有什么问题,但是很多人经常写着写着就忘关闭文件了。
再想象一下,此时你打开文件,紧接着就是一个defer语句关闭文件,这样就不会写着写着忘记了,defer也会自动帮你关闭。
性能开销
目前为止(go 1.15),defer的性能已经算不错了,但是还是不可避免的有开销。
虽然go本身就不是搞性能要求高领域的,但还是要防止滥用,有更好的解决方案就不应该偷懒用defer。