defer 关键字将其后的语句推迟到所在函数返回之前执行,常用于资源释放:关闭文件、解锁、关闭连接等。
1. 基本用法
func readFile(path string) {
f, err := os.Open(path)
if err != nil {
return
}
defer f.Close() // 无论函数从哪里返回,Close 都会执行
// ... 读写文件
}
把 Close 和 Open 写在相邻位置,不容易因为中途 return 或 panic 而忘记释放资源。
2. 执行顺序:后进先出
一个函数中可以有多个 defer,它们按声明顺序的逆序执行,类似栈:
func main() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
}
// 输出:3 2 1
3. 参数值在 defer 语句时确定
defer 语句执行时,函数的参数会立即求值并复制,不会等到实际执行时:
i := 0
defer fmt.Println("defer:", i) // 此刻 i 的值 0 已被复制
i = 10
// 函数结束输出:defer: 0
// 如果希望拿到最终值,用闭包引用变量
i = 0
defer func() { fmt.Println("defer:", i) }()
i = 10
// 输出:defer: 10
4. defer 与返回值
命名返回值可以在 defer 中被修改:
func f() (result int) {
defer func() {
result++ // 修改了命名返回值
}()
return 1 // 实际返回 2
}
匿名返回值则不受影响,因为 return 时值已经复制出去。defer 中修改返回值是 double check、资源清理记录日志等场景的基础,但也会降低可读性,不要滥用。
5. defer 与 recover
defer 中的函数可以配合 recover 捕获 panic,这是 Go 语言恢复程序运行的唯一手段,下一节错误处理会详细展开。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END









暂无评论内容