简介
defer
是 Golang 中的一个非常有用的关键字,它用于注册延迟调用,也就是一个函数的执行被延迟到调用它的函数返回之后,常用于资源清理、异常处理等场景。
示例
defer 是注册演示执行, 只有再函数返回或者发生panic的时候才会执行, 同时 同一个函数内的多个 defer 注册的调用也遵循先进后出的栈调用原则.
下面是一个用于理解的示例:
package main
import (
"fmt"
)
func main() {
defer func() {
fmt.Println("第一个defer")
}()
defer func() {
fmt.Println("第二个defer")
}()
fmt.Println("主程序执行完毕")
// panic("发生panic了")
return
}
如上所示, 我们按照顺序使用了两个 defer, 执行结果如下:
表示两个 defer 都是再return 之后执行的, 而且遵守先进后出的原则.
使用场景
defer
主要用于函数结束前的清理工作,例如在打开文件后 defer 关闭文件,或者在打开数据库后 defer 关闭数据库连接, 还有处理捕获异常.
捕获异常
在 Go
中,异常处理使用了 panic-recover
,当执行较长的代码块时,可能会因为一些不可预见的原因导致程序出现异常,此时可以使用 defer
语句在 panic 发生时自动执行一些清理工作并进行异常处理。例如:
package main
import (
"fmt"
)
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("defer-recover 开始处理 panic, 不要慌")
fmt.Println(err)
}
}()
fmt.Println("开始干活了")
panic("发生panic了")
}
上述代码中,在 main
执行过程中如果出现了 panic,会在 defer 中注册的函数执行后进行异常恢复, 同时打印出对应的信息
执行结果如下:
发现, panic发生之后, 执行了 defer 的代码, 还获取到了 panic的信息
文件操作
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.OpenFile("text.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)
if err != nil {
fmt.Println(err)
}
defer f.Close()
n, err := f.WriteString("大家号, 这是一个文件\t")
if err != nil {
fmt.Println(err)
}
fmt.Println(n)
}
上面的代码中, 我们使用 defer 延迟调用释放资源,防止忘记释放资源(关闭文件或解锁), 这样就可以在函数结束的时候自动关闭文件了