概述
一个 defer
语句就是一个一般的函数或办法调用。 defer
语句保障了不论是在失常状况下 (return 返回),
还是非正常状况下 (产生谬误, 程序终止),函数或办法都可能执行。
次要个性
- 一个函数可定义多个
defer
语句 defer
表达式中的变量值在defer
表达式定义时曾经确定defer
表达式能够批改函数中的命名返回值
次要作用
- 简化异样解决 (应用
defer
+recover
),防止异样与控制流混合在一起 (try … catch … finally
) - 在
defer
做资源开释和配置重置等收尾工作
语法规定
如果 defer
函数只有一行语句,能够省略 func() { ...}
代码块,否则就须要用 func() { ...}
代码块包起来。
多个 defer 执行程序
如果一个函数中注册了多个 defer
函数,这些函数会依照 后进先出
的程序执行 (和 栈
的出栈程序统一)。
也就是最初注册的 defer 函数会第一个执行,而第一个注册的 defer
函数会最初执行。
例子
函数退出前打印字符
package main
func A() {defer println("A 函数执行实现")
println("A 函数开始执行")
}
func B() {defer println("B 函数执行实现")
println("B 函数开始执行")
}
func main() {A()
B()}
// $ go run main.go
// 输入如下
/**
A 函数开始执行
A 函数执行实现
B 函数开始执行
B 函数执行实现
*/
敞开文件句柄
package main
import (
"fmt"
"os"
)
func createFile(name string) *os.File {file, err := os.Create(name)
if err != nil {panic(err)
}
return file
}
func writeFile(file *os.File) {n, err := file.WriteString("hello world")
if err != nil {panic(err)
} else {fmt.Printf("胜利写入 %d 个字符 \n", n)
}
}
func closeFile(file *os.File) {err := file.Close()
if err != nil {panic(err)
}
}
func main() {file := createFile("/tmp/defer_test.txt")
defer closeFile(file) // 获取到文件句柄后,第一工夫注册 defer 函数
writeFile(file)
}
// $ go run main.go
// 输入如下
/**
胜利写入 11 个字符
*/
// $ cat /tmp/defer_test.txt
// 输入如下
/**
hello world
*/
多个 defer 函数
package main
func A() {defer println("第 1 个 defer 函数")
defer func() { // 这里为了演示 func() {...} 的语法
defer println("第 2 个 defer 函数")
}()
defer println("第 3 个 defer 函数")
println("A 函数开始执行")
}
func main() {A()
}
// $ go run main.go
// 输入如下
/**
A 函数开始执行
第 3 个 defer 函数
第 2 个 defer 函数
第 1 个 defer 函数
*/
reference
- Go 圣经