
defer的使用
✅ 1. defer 是函数级别的
defer绑定在当前函数的作用域中。- 当当前函数执行完毕(无论是正常返回、
return、还是panic),所有在该函数中注册的defer语句都会被执行。 - 即使函数中有多个
return分支,defer也一定会执行(除非程序提前退出,如os.Exit())。
✅ 结论:只要函数开始执行,并且执行到了 defer 语句(注意:defer 是运行时注册的,不是编译时),那么当函数退出时,defer 就会执行。
⚠️ 注意:如果函数因为 panic 而崩溃,
defer依然会执行(这是实现 recover 的基础)。
✅ 2. 多个 defer 的执行顺序:后进先出(LIFO)
Go 中的 defer 遵循 “栈” 的原则:最后注册的 defer 最先执行。
示例:
go
package main
import "fmt"
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
fmt.Println("main running")
}输出:
main running
3
2
1执行顺序:
defer按代码顺序注册 → 执行时逆序调用。
✅ 3. defer 的参数在注册时求值
这是一个常见陷阱!
go
func main() {
i := 0
defer fmt.Println("i =", i) // 这里 i 的值是 0(立即求值)
i = 100
fmt.Println("end")
}输出:
end
i = 0如果你希望使用“函数结束时”的变量值,需要用匿名函数捕获:
go
defer func() {
fmt.Println("i =", i) // 此时 i 是 100
}()✅ 4. 特殊情况:os.Exit() 会跳过 defer
go
func main() {
defer fmt.Println("不会打印!")
os.Exit(1)
}→ defer 不会执行,因为 os.Exit() 直接终止进程。
总结
| 问题 | 答案 |
|---|---|
defer 是函数级别的吗? | ✅ 是,绑定到当前函数 |
函数执行完就执行 defer 吗? | ✅ 是(包括 panic,但不包括 os.Exit()) |
多个 defer 执行顺序? | 🔁 后注册的先执行(LIFO 栈顺序) |
defer 参数何时求值? | 🕒 注册时立即求值(除非用闭包) |

