MST

星途 面试题库

面试题:Go defer 在异常处理场景下的深度剖析

在 Go 语言中,假设存在一个复杂的业务逻辑函数,其中包含多层嵌套调用以及多个 defer 语句,同时还需要处理各种可能的异常情况。请详细阐述 defer 在这种异常处理场景下是如何工作的,包括它与 recover 机制的交互细节,并且通过一段完整的示例代码展示其具体行为和应对策略。
29.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

defer 在异常处理场景下的工作原理

  1. 执行时机:defer 语句会在包围它的函数即将返回时执行,无论该函数是正常返回还是因为 panic 而异常终止。多个 defer 语句会按照后进先出(LIFO)的顺序执行。
  2. 与异常的关系:当函数发生 panic 时,正常的执行流程被中断,但 defer 语句仍然会被执行。这使得 defer 可以用于释放资源,比如关闭文件、数据库连接等,即使在异常情况下也能保证资源的正确清理。
  3. 与 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")
}

代码说明

  1. complexBusinessLogic 函数:定义了一个模拟资源,并在 defer 匿名函数中释放资源。同时,defer 函数中使用 recover 捕获可能发生的 panic。
  2. 多层嵌套调用complexBusinessLogic 调用 nestedCall1nestedCall1 又调用 nestedCall2,模拟了多层嵌套的业务逻辑。
  3. nestedCall2 函数:故意触发一个 panic,模拟业务逻辑中的异常情况。
  4. main 函数:调用 complexBusinessLogic,展示整个执行流程。

输出结果

Starting main
Releasing resource: some resource
Recovered from panic: Simulated panic in nestedCall2
Ending main

可以看到,尽管 nestedCall2 触发了 panic,但 defer 函数仍然执行了资源释放操作,并且通过 recover 捕获并处理了 panic,使得 main 函数能够继续执行到结束。