# go的defer关键字作用?

官方叫做:Defer statements延期声明 (opens new window)

# 核心作用与执行时机

  • 延迟执行defer 后面的函数调用不会立即执行,而是会被压入一个栈中,等外层函数执行完毕(正常返回或发生 panic)前,再按后进先出(LIFO) 的顺序执行。
  • 参数预计算defer 语句中的参数(包括接收者)会在声明 defer 时就立即求值,而不是等到实际调用时才求值。

# 外层函数执行完毕是指?

“外层函数”就是包含 defer 语句的那个函数,也就是 defer 代码块所在的函数。

举个例子你就明白了

func outer() {          // 这个就是“外层函数”
    fmt.Println("开始")
    
    defer fmt.Println("延迟执行")  // defer 语句在 outer 函数内部
    
    fmt.Println("结束")
    // 此时 outer 函数即将返回
    // 在返回之前,会执行上面 defer 的那个 "延迟执行"
}

func main() {
    outer()
}
1
2
3
4
5
6
7
8
9
10
11
12
13

执行顺序:

  1. 打印 "开始"
  2. 遇到 defer,不立即执行,只是把 fmt.Println("延迟执行") 压入栈
  3. 打印 "结束"
  4. outer 函数即将返回时,从栈中弹出 defer 内容,执行 "延迟执行"

# 外层是什么意思?

  • 相对于 defer 语句本身:defer 自己写在某个函数的“里面”,那么这个函数就是它的“外层”函数。
  • 不是指 main 函数,也不是指全局环境,就是指直接包裹 defer 的那个函数

如果 defer 嵌套在多层函数调用中:

func level1() {
    defer fmt.Println("level1 的 defer")
    level2()
}

func level2() {
    defer fmt.Println("level2 的 defer")
    fmt.Println("level2 执行")
}
1
2
3
4
5
6
7
8
9
  • level2 中的 defer 会在 level2 函数返回前执行。
  • level1 中的 defer 会在 level1 函数返回前执行。

总结一句话

defer 延迟执行的是它所在的函数的结尾处,而不是整个程序或其他函数的结尾。

# 核心要点总结

序号 要点 说明
1 执行时机 defer 将函数调用推迟到外围函数返回之前执行(正常返回、执行到末尾或 panic 时都会触发)。
2 语法限制 defer 后必须是函数或方法调用,不能加括号。内置函数的使用受常规表达式语句规则限制。
3 参数预求值 defer 语句执行时,函数值和参数立即求值并保存,但函数本身不执行。
4 调用顺序 多个延迟函数按后进先出(LIFO) 的顺序执行(即最后一个 defer 最先执行)。
5 return 的关系 若外围函数有显式 return,延迟函数在结果参数被设置之后、函数返回调用者之前执行。
6 nil 函数值 若延迟的函数值为 nil,则在调用该函数时(即返回前夕)发生 panic,而不是在 defer 语句处。
7 修改命名返回值 如果延迟函数是函数字面量,且外围函数有命名返回值,延迟函数可以访问并修改它们。
8 延迟函数的返回值 延迟函数自己的返回值会被丢弃,不影响外围函数的结果。

这段描述是 Go 语言规范中 defer 最权威的定义,所有 defer 的行为都严格遵循以上规则。

Last Updated: 6/3/2026, 4:53:54 AM