Golang官方文档中提到,defer关键字修饰的语句会被记录在一个列表中,并在当前方法返回之前一并执行。在Golang中,defer关键字通常用来处理一些清理和释放资源的操作。
例如,这里有一个调用两个文件进行内容复制的函数:
1 |
|
这个函数中存在一个bug。当os.Create(dstName)调用出现异常时,方法会提前返回,导致打开的资源没有被释放。
若我们使用defer则可解决这一个bug:
1 |
|
在这一个用上defer的例子中,在os.Create(dstName)调用前,src.Close()已被存入返回前的调用列表中。当os.Create(dstName)出现异常导函数提早返回时,src.Close()依然会被调用。
defer修饰的语句表现结果可依据以下三个规则进行判断:
1、defer修饰一个函数调用时,函数的参数也会按照当前的参数结果推移至返回前
例如:
1 |
|
2、defer修饰的语句会以FILO的顺序在返回前被调用
官方文档中对defer修饰的语句的保存说明为:A defer statement pushes a function call onto a list. (一个defer语句推动一个函数调用到列表中)。但其实际为栈的FILO的输入输出表现。
例如:
1 |
|
3、defer修饰的函数可以读取和修改给返回函数的命名返回值。
例如:
1 |
|
这个示例函数还涉及到defer使用常踩的一个坑。那就是return返回结果并不是一个原子操作。前面说到,defer修饰语句是在return返回之前调用,因此这个示例等价于:
1 |
|
只要理解这三个规则,在使用defer就自然心中有数了。