关键字 defer 在 Go 中将所指定的函数执行推迟到周围函数的退出 — 函数会积累在栈中并以相反的顺序执行 (LIFO)。这常用于释放资源(文件,互斥锁,连接)。
特点是 — 所有传递给 defer 的函数的参数在声明时立即计算,而不是在执行时。
func test() { for i := 0; i < 3; i++ { defer fmt.Println(i) // 打印: 2, 1, 0 } }
以下代码将输出什么?
func main() { for i := 0; i < 3; i++ { defer fmt.Println(i) } }
答案:
这将输出:
2
1
0
因为在每个循环中,参数 i 被立即计算(在 defer 时候),所有值被存储在 defer 的栈中。
故事
在文件服务中忘记考虑 defer 仅在正常退出函数时被调用的问题。程序在 defer 调用之前意外终止时出现泄漏。
故事
在数据管道中发生了遗忘 — 在循环中使用 defer 来关闭连接,但实际上它们只在整个函数完成后关闭,而不是在每次迭代后。这导致资源耗尽。
故事
在记录器中使用 defer 和匿名函数,以为参数在调用时计算。结果是日志的最后部分包含过时的信息,因为值在之前就被捕获了。