【go语言】2.3.3 defer, panic 和 recover

172 阅读2分钟

在 Go 语言中,deferpanic 和 recover 是三个用于处理错误和异常的重要关键字。

defer

defer 关键字用于确保一个函数调用在程序执行结束后会被调用,无论函数是否出现错误。它通常用于清理资源,如关闭文件、解锁互斥锁等。

func foo() {
    file, err := os.Open("file.txt")
    if err != nil {
        log.Fatal(err)
    }

    // 确保文件在函数结束时关闭
    defer file.Close()

    // 继续处理文件...
}

在这个例子中,file.Close() 会在 foo() 函数结束时被调用,无论函数是否正常结束还是因为错误而返回。

panic

panic 函数用于生成一个运行时错误,它会停止当前函数的执行,并开始回溯(unwinding)过程,即运行在当前 Goroutine 中被延迟(deferred)的函数,然后返回到 Goroutine 的调用者。这个过程会一直持续,直到当前 Goroutine 中的所有函数都返回为止,然后程序会终止。

func foo() {
    // ...
    panic("something went wrong")
    // ...
}

在这个例子中,当 panic 被调用时,它会立即停止 foo 函数的执行,并开始运行被延迟的函数(如果有的话)。

recover

recover 函数用于捕获 panic 异常。如果没有发生 panic,调用 recover 会返回 nil,否则它会捕获 panic 的值,让程序恢复正常执行。

recover 只在被 defer 调用的函数中有效。在正常的执行过程中,调用 recover 会不起作用。

func foo() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in foo", r)
        }
    }()

    fmt.Println("Calling g.")
    g(0)
    fmt.Println("Returned normally from g.")
}

func g(i int) {
    if i > 3 {
        fmt.Println("Panicking!")
        panic(fmt.Sprintf("%v", i))
    }
    defer fmt.Println("Defer in g", i)
    fmt.Println("Printing in g", i)
    g(i + 1)
}

在这个例子中,当 g 函数在 i > 3 时调用 panic,执行过程会立即停止,然后运行 g 和 foo 中的被 defer 调用的函数。在 foo 的 defer 函数中,recover 被调用并捕获 panic 的值,然后打印出一个消息,并让程序恢复正常执行。

理解 deferpanic 和 recover 是编写 Go 程序的重要部分,它们提供了一种强大的控制流程的机制,可以用来处理错误和异常情况。 推荐阅读:

mp.weixin.qq.com/s/dV2JzXfgj…

mp.weixin.qq.com/s/an83QZOWX…

file