背景
在开发过程中,经常发现 defer xxx(),具体干什么用的呢?
概念
defer 用于在 go 中进行尾调工作,比如资源回收,延迟执行等
执行逻辑
- 在父函数的 return 语句执行之后,返回值之前执行,或者 panic 后
- 多个 defer,采用的栈顺序执行,LIFO
package main
import "fmt"
func example1() {
fmt.Println("开始")
defer fmt.Println("defer 1")
defer fmt.Println("defer 2")
defer fmt.Println("defer 3")
fmt.Println("结束")
}
func main() {
example1()
}
输出
开始
结束
defer 3
defer 2
defer 1
panic 后执行
package main
import "fmt"
func example6() {
defer fmt.Println("defer 1")
defer fmt.Println("defer 2")
fmt.Println("准备 panic")
panic("出错了!")
defer fmt.Println("defer 3") // 不会执行
fmt.Println("这行不会执行")
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("捕获 panic:", r)
}
}()
example6()
}
输出
准备 panic
defer 2
defer 1
捕获 panic: 出错了!
配合 context 的使用:幂等函数 + defer = 防弹式资源管理
package main
import (
"context"
"fmt"
"sync"
"time"
)
func worker(ctx context.Context, id int, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case <-ctx.Done():
fmt.Printf("Worker %d stopping: %v\n", id, ctx.Err())
return
default:
fmt.Printf("Worker %d processing...\n", id)
time.Sleep(500 * time.Millisecond)
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
defer cancel()
// 启动5个 worker
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(ctx, i, &wg)
}
// 运行3秒后停止所有 worker
time.Sleep(3 * time.Second)
fmt.Println("Stopping all workers...")
cancel() // 一次调用,停止所有 worker
wg.Wait()
fmt.Println("All workers stopped")
}