概述
一个defer
语句就是一个普通的函数或方法调用。defer
语句保证了不论是在正常情况下 (return 返回), 还是非正常情况下 (发生错误, 程序终止),函数或方法都能够执行。
主要特性
-
•一个函数可定义多个
defer
语句 -
•
defer
表达式中的变量值在defer
表达式定义时已经确定 -
•
defer
表达式可以修改函数中的命名返回值
主要作用
-
•简化异常处理 ( 使用
defer
+recover
),避免异常与控制流混合在一起 (try … catch … finally
) -
•在
defer
做资源释放和配置重置等收尾工作
语法规则
如果defer
函数只有一行语句,可以省略func() { ... }
代码块,否则就需要用func() { ... }
代码块包起来。
多个 defer 执行顺序
如果一个函数中注册了多个defer
函数,这些函数会按照后进先出
的顺序执行 (和栈
的出栈顺序一致)。也就是最后注册的 defer 函数会第一个执行,而第一个注册的defer
函数会最后执行。
例子
函数退出前打印字符
packagemain
funcA(){
deferprintln("A函数执行完成")
println("A函数开始执行")
}
funcB(){
deferprintln("B函数执行完成")
println("B函数开始执行")
}
funcmain(){
A()
B()
}
//$gorunmain.go
//输出如下
/**
A函数开始执行
A函数执行完成
B函数开始执行
B函数执行完成
*/
关闭文件句柄
packagemain
import(
"fmt"
"os"
)
funccreateFile(namestring)*os.File{
file,err:=os.Create(name)
iferr!=nil{
panic(err)
}
returnfile
}
funcwriteFile(file*os.File){
n,err:=file.WriteString("helloworld")
iferr!=nil{
panic(err)
}else{
fmt.Printf("成功写入%d个字符\n",n)
}
}
funccloseFile(file*os.File){
err:=file.Close()
iferr!=nil{
panic(err)
}
}
funcmain(){
file:=createFile("/tmp/defer_test.txt")
defercloseFile(file)//获取到文件句柄后,第一时间注册defer函数
writeFile(file)
}
//$gorunmain.go
//输出如下
/**
成功写入11个字符
*/
//$cat/tmp/defer_test.txt
//输出如下
/**
helloworld
*/
多个 defer 函数
packagemain
funcA(){
deferprintln("第1个defer函数")
deferfunc(){//这里为了演示func(){...}的语法
deferprintln("第2个defer函数")
}()
deferprintln("第3个defer函数")
println("A函数开始执行")
}
funcmain(){
A()
}
//$gorunmain.go
//输出如下
/**
A函数开始执行
第3个defer函数
第2个defer函数
第1个defer函数
*/
reference
- 1.Go 圣经 (https://book.douban.com/subject/27044219)