Skip to content
鼓励作者:欢迎打赏犒劳

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 参数何时求值?🕒 注册时立即求值(除非用闭包)

如有转载或 CV 的请标注本站原文地址