MST

星途 面试题库

面试题:Go语言错误处理机制的深入探讨

Go语言中通过`defer`、`recover`结合处理异常。请描述`defer`、`recover`的工作原理,并编写一段代码,在函数中故意引发一个`panic`,然后使用`defer`和`recover`来捕获并处理这个`panic`,同时解释这样做如何在复杂业务逻辑中保证程序的稳定性。另外,说明错误包装(`fmt.Errorf` 配合 `%w`)在处理多层调用传递错误时的作用和优势。
18.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

defer 工作原理

defer 语句用于延迟函数的执行,直到包含该 defer 语句的函数返回。当 defer 语句被执行时,其后面的函数调用会被压入一个栈中。当外层函数执行完毕准备返回时,这些被延迟的函数调用会按照后进先出(LIFO)的顺序依次执行。

recover 工作原理

recover 是一个内置函数,用于在 defer 函数中捕获 panic。当 panic 发生时,程序会立即停止当前函数的正常执行,开始展开栈(unwind),执行所有被延迟的函数。如果在某个被延迟的函数中调用了 recover,并且当前存在一个 panic,那么 recover 会捕获这个 panic,停止栈的展开,使程序可以继续正常执行。

代码示例

package main

import (
    "fmt"
)

func main() {
    test()
}

func test() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    fmt.Println("Before panic")
    panic("故意引发的 panic")
    fmt.Println("After panic") // 这行代码不会被执行
}

在复杂业务逻辑中保证程序稳定性

在复杂业务逻辑中,deferrecover 可以防止程序因 panic 而崩溃。通过在关键函数中使用 deferrecover,即使某个子操作发生 panic,也能确保程序可以捕获异常并进行适当处理,从而维持程序的运行,避免整个系统崩溃。这有助于提高系统的容错性和稳定性,特别是在处理资源管理、事务处理等关键业务场景时。

错误包装(fmt.Errorf 配合 %w)的作用和优势

  1. 作用:错误包装允许将一个错误包装在另一个错误中,同时保留原始错误信息。这在多层函数调用中非常有用,因为上层函数可以通过错误包装来传递底层函数返回的错误,同时添加更多上下文信息。
  2. 优势
    • 保留原始错误信息:通过 %w 格式化动词,原始错误被包含在新的错误中,使得在调试和处理错误时能够获取到完整的错误链。
    • 方便错误处理:在调用栈的不同层次,可以通过 errors.Iserrors.As 函数来检查和提取特定类型的错误,从而进行针对性的处理。这使得错误处理更加灵活和精确,有助于编写健壮的错误处理逻辑。

例如:

package main

import (
    "errors"
    "fmt"
)

var ErrSpecific = errors.New("specific error")

func inner() error {
    return ErrSpecific
}

func outer() error {
    err := inner()
    if err != nil {
        return fmt.Errorf("outer function failed: %w", err)
    }
    return nil
}

func main() {
    err := outer()
    if err != nil {
        if errors.Is(err, ErrSpecific) {
            fmt.Println("Caught specific error:", err)
        }
    }
}

在这个例子中,outer 函数将 inner 函数返回的错误进行了包装,并且在 main 函数中可以通过 errors.Is 函数来判断是否是特定类型的错误。