Skip to content

defer 关键字

defer 英文释义为“延迟”,有点意思,使用defer注册一个函数调用,使其在包含它的函数即将返回时执行

go
func DeferTest() {
    fmt.Println("Defer 执行")
}
func Worker() int {
    fmt.Println("Do something 01")
    defer DeferTest()
    fmt.Println("Do something 02")
    return -1
}
func main() {
    fmt.Println("函数执行完毕, 返回值为", Worker())
}

执行结果 ——

text
Do something 01
Do something 02
Defer 执行
函数执行完毕, 返回值为 -1

我们在Worker中使用defer注册了DeferTest的函数调用,不管注册的位置在哪,它都是在return前再执行

注意

其中,如果我们使用defer注册了多个函数,那么都会被压入栈内,从而实现FISO(先进后出)的调用顺序。

底层原理

Go 运行时为每个活跃的 goroutine 维护一个 defer 栈。编译器在每个包含 defer 的函数入口处初始化这个栈,遇到 defer 时将对应信息推入。函数返回时,会跳转到一个专门的清理逻辑,遍历执行所有 defer 调用。

常用

  • 锁管理:在获取锁后立即 defer mu.Unlock(),确保函数任何返回路径都能释放锁。
  • 连接与文件关闭defer conn.Close()defer file.Close() 保证资源释放,避免泄漏。
  • 取消 Contextctx, cancel := context.WithCancel() 后用 defer cancel() 避免 goroutine 泄漏。

有时候通道的释放closedefer修饰也是一种不错的方法

Released under the MIT License.