Skip to content

Go错误处理:Panic和Recover

Panic

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为 0了)。才使用Go中引入的Exception处理:defer, panic, recover。

这几个异常的使用场景可以这么简单描述:Go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。

可以将 panic 想象成一种病毒,因为它会在程序中不断向上传播,直到最终导致程序崩溃。当发生 panic 时,程序会立即停止当前函数的执行,并开始向上返回调用栈,依次执行每个函数的 defer,直到到达最外层的函数为止。在这个过程中,如果有函数中的 defer 使用了 recover() 来捕获 panic,并且处理了异常,那么程序可能会继续执行下去,否则会导致程序崩溃。

因此,如果 panic 没有得到适当处理,它的确会像一种病毒一样在程序中传播,最终导致整个程序的崩溃。这也是在编写 Go 代码时需要注意避免滥用 panic,以及确保正确处理异常的重要原因之一。

实例

go
package main

import "fmt"

func main(){
    fmt.Println("c")
     defer func(){ // 必须要先声明defer,否则不能捕获到panic异常
        fmt.Println("d")
        if err:=recover();err!=nil{
            fmt.Println(err) // 这里的err其实就是panic传入的内容,55
        }
        fmt.Println("e")
    }()

    f() //开始调用f
    fmt.Println("f") //这里开始下面代码不会再执行
}

func f(){
    fmt.Println("a")
    panic("异常信息")
    fmt.Println("b") //这里开始下面代码不会再执行
    fmt.Println("f")
}

输出结果:

text
c
a
d
异常信息
e

解释:代码由上向下执行。遇到defer func,将对应内容压入栈等待执行;调用func f时出现了panic,逆序调用defer func实现错误处理.在发生 panic 后,程序将立即转移到 defer 声明的函数,而 panic 发生后,当前函数内剩余的代码将不再执行。在这段代码中,defer 声明了一个匿名函数,其中包含了对 recover() 的调用。当 panic 发生时,程序会立即跳转到这个匿名函数,并执行其中的代码。recover() 函数会捕获当前的 panic 异常,并返回其传递的值(在这个例子中就是 "异常信息"),如果没有发生 panicrecover() 返回 nil。然后,程序继续执行匿名函数中的其他代码,即输出 "异常信息" 后面的 "e"。

Recover

在Go语言中,recover 函数用于在 defer 声明的函数中捕获 panic 异常。当 panic 发生时,recover 可以用于恢复程序的执行,并获取 panic 传递的值。

recover() 函数的逻辑是用于从 panic 异常中恢复,并且只能在 defer 声明的函数中使用。当程序在执行过程中发生了 panic,如果有 defer 声明的函数调用了 recover(),则程序会从 panic 的位置恢复执行。

recover() 有以下几个特点和逻辑:

  1. recover() 只能在 defer 声明的函数中有效。如果在没有发生 panic 的情况下调用 recover(),它会返回 nil
  2. 如果在 defer 声明的函数中调用了 recover(),并且在该函数内发生了 panicrecover() 将会返回 panic 的值,并且 panic 的流程会被停止。
  3. 如果在 defer 声明的函数中调用了 recover(),但是在该函数内并未发生 panicrecover() 会返回 nil
  4. 如果在 defer 声明的函数外调用 recover(),它将返回 nil,并且不会对 panic 进行捕获和处理。

一般情况下,recover() 用于从 panic 中恢复,并执行一些必要的清理工作或者进行错误处理,以保证程序的正常运行或者优雅地处理异常情况。