Go延迟执行defer
defer语句延迟函数执行到函数返回前,常用于资源清理。
defer基本用法
基本语法
Go
func readFile() {
file, err := os.Open("data.txt")
if err != nil {
return
}
defer file.Close() // 函数返回前执行
// 读取文件...
}
多个defer
Go
func process() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
fmt.Println("执行")
}
// 输出顺序:
// 执行
// 3
// 2
// 1
多个defer按声明顺序逆序执行(栈结构)。
defer执行时机
函数返回前
Go
func example() int {
defer fmt.Println("defer执行")
fmt.Println("函数体")
return 10
}
// 输出顺序:
// 函数体
// defer执行
return之后
Go
func example() int {
defer fmt.Println("defer")
return 10
// return之后执行defer
}
defer参数评估
参数立即评估
Go
func example() {
i := 1
defer fmt.Println(i) // 参数i在此时已确定为1
i++
fmt.Println("函数内:", i) // 2
}
// 输出:
// 函数内: 2
// defer: 1 // defer打印1,参数已评估
defer参数在声明时评估,不是执行时。
闭包捕获变量
Go
func example() {
i := 1
defer func() {
fmt.Println(i) // 闭包捕获i,执行时打印2
}()
i++
}
// 输出:
// defer: 2 // 执行时才取i的值
defer与返回值
命名返回值影响
Go
func example() (n int) {
defer func() {
n++ // 可修改命名返回值
}()
return 10
}
fmt.Println(example()) // 11
非命名返回值不影响
Go
func example() int {
n := 10
defer func() {
n++ // 修改局部变量,不影响返回值
}()
return n // 返回10
}
fmt.Println(example()) // 10
defer常见用途
资源释放
Go
func process() {
mu.Lock()
defer mu.Unlock() // 确保释放锁
// 处理...
}
文件关闭
Go
func read() {
file, _ := os.Open("data.txt")
defer file.Close()
// 读取...
}
错误恢复
Go
func safeProcess() {
defer func() {
if r := recover(); r != nil {
fmt.Println("恢复:", r)
}
}()
panic("出错")
}
打印调试
Go
func trace(name string) func() {
fmt.Println("进入:", name)
return func() {
fmt.Println("退出:", name)
}
}
func process() {
defer trace("process")()
// 处理...
}
defer执行顺序图
text
┌─────────────────────────────────────┐
│ 函数体执行 │
│ │
│ defer A → 压入栈 │
│ defer B → 压入栈 │
│ defer C → 压入栈 │
│ │
│ return │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ defer栈弹出执行 │
│ │
│ C → B → A(逆序) │
└─────────────────────────────────────┘
defer特性总结
| 特性 | 说明 |
|---|---|
| 执行时机 | 函数返回前 |
| 执行顺序 | 逆序(栈) |
| 参数评估 | 声明时评估 |
| 闭包捕获 | 执行时取值 |
| 命名返回值 | 可修改 |
| 非命名返回值 | 不可修改 |
要点总结
- defer延迟执行到函数返回前
- 多defer逆序执行(栈结构)
- defer参数声明时立即评估
- 闭包defer执行时才取变量值
- defer可修改命名返回值
- 常用于资源释放、错误恢复
- defer紧跟资源获取语句
📝 发现内容有误?点击此处直接编辑