面试题答案
一键面试defer 在异常处理场景下的工作原理
- 执行时机:defer 语句会在包围它的函数即将返回时执行,无论该函数是正常返回还是因为 panic 而异常终止。多个 defer 语句会按照后进先出(LIFO)的顺序执行。
- 与异常的关系:当函数发生 panic 时,正常的执行流程被中断,但 defer 语句仍然会被执行。这使得 defer 可以用于释放资源,比如关闭文件、数据库连接等,即使在异常情况下也能保证资源的正确清理。
- 与 recover 机制的交互:recover 是一个内置函数,用于在发生 panic 时恢复程序的正常执行流程。它只能在 defer 函数中被调用才会生效。如果在 defer 函数中调用 recover,并且当前存在 panic,则 recover 会捕获 panic 的值并使程序从 panic 中恢复,继续执行 defer 函数之后的代码。如果当前没有 panic,recover 会返回 nil。
示例代码
package main
import (
"fmt"
)
func complexBusinessLogic() {
// 模拟资源,这里用一个简单的变量表示
resource := "some resource"
defer func() {
// 释放资源
fmt.Println("Releasing resource:", resource)
if r := recover(); r != nil {
// 捕获 panic 并处理
fmt.Println("Recovered from panic:", r)
}
}()
// 模拟多层嵌套调用
nestedCall1()
}
func nestedCall1() {
nestedCall2()
}
func nestedCall2() {
// 模拟可能出现异常的操作
panic("Simulated panic in nestedCall2")
}
func main() {
fmt.Println("Starting main")
complexBusinessLogic()
fmt.Println("Ending main")
}
代码说明
complexBusinessLogic
函数:定义了一个模拟资源,并在 defer 匿名函数中释放资源。同时,defer 函数中使用 recover 捕获可能发生的 panic。- 多层嵌套调用:
complexBusinessLogic
调用nestedCall1
,nestedCall1
又调用nestedCall2
,模拟了多层嵌套的业务逻辑。 nestedCall2
函数:故意触发一个 panic,模拟业务逻辑中的异常情况。main
函数:调用complexBusinessLogic
,展示整个执行流程。
输出结果
Starting main
Releasing resource: some resource
Recovered from panic: Simulated panic in nestedCall2
Ending main
可以看到,尽管 nestedCall2
触发了 panic,但 defer 函数仍然执行了资源释放操作,并且通过 recover 捕获并处理了 panic,使得 main
函数能够继续执行到结束。