这个defer绝对是在其他编程语言中很难遇到的东西,是Go语言里独有的关键字,但你可能也会在其他编程语言中找到类似的影子,比如C++的析构函数,但是他们大不相同(defer实现在函数里面)。go 语言的defer功能强大,对于资源管理非常方便,但是如果没用好,也会有陷阱。
defer的使用场景
一般来讲,我们把defer用于以下场景中:
- 关闭文件句柄
- 锁资源释放
- 数据库连接释放
- 处理异常,特别是一些很难捕捉到到异常(来源于操作系统内核或者硬件提示的异常信息)
defer的特性
- 关键字 defer 用于注册延迟调用
- 这些调用直到包含该defer语句的函数执行完毕时(无论是正常的return返回,还是由于panic异常导致结束)才被执行
- 多个defer语句,按先进后出的方式执行,即与声明的顺序相反
- defer语句中的变量,在defer声明时就决定了,即当defer被声明时,其参数就会被实时解析
- defer可以读取有名返回值
func deferFunc1() (i int ) {
defer func() { i++ }()// step2: 会继续操作i++
return i // step1: 返回值会复制给一个临时变量,再返回出去
}
defer碰上闭包
package main
import "fmt"
func main() {
var whatever [5]struct{}
for i := range whatever {
defer func() { fmt.Println(i) }()
}
}
//输出结果
4
4
4
4
4
函数正常执行,由于闭包用到的变量 i 在执行的时候已经变成4,所以输出全都是4。
另外要注意,滥用 defer 可能会导致性能问题,尤其是在一个 "大循环" 里。所以这里也需要切记不能滥用。 更多可以参考函数function的第八部分。
这部分内容就总结到这里,了解了不?