编程Go 开发者

解释 Go 中的 defer 是如何工作的,何时调用顺序可能会变得出乎意料。在实践中有哪些潜在问题?

用 Hintsage AI 助手通过面试

答案。

关键字 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 和匿名函数,以为参数在调用时计算。结果是日志的最后部分包含过时的信息,因为值在之前就被捕获了。