• 首页
  • go
  • go 语言中的错误捕捉 panic 以及 recover修复错误

go 语言中的错误捕捉 panic 以及 recover修复错误


文章目录



go语言中的错误处理

go语言中遇到错误,一般直接返回 error ,如果手动无法处理的 error ,可以直接触发 panic .
当遇到一些严重错误,比如数组,切片越界等错误,直接 panic 也会被触发.
panic 一但被触发,当前执行的程序会退出.

package main

import (
    "fmt"
)


func main() {

    fmt.Println("before panic")
    panic("program crash")
    fmt.Println("after panic")

}

执行结果:

./prog.go:24:2: unreachable code
Go vet exited.

before panic
panic: program crash

goroutine 1 [running]:
main.main()
    /tmp/sandbox099230355/prog.go:23 +0x95

我们可以看到 panic 触发前的信息打印出来了 "before panic"
但是触发 panic 后的信息没有打印出来,报错直接退出了当前程序.


当 panic 遇上 defer

panic 触发后会终止当前程序,但是在终止程序之前,
会把当前协程上所有 defer 的任务,全部处理完成后才退出.
panic 的这种机制类似于 java / c#等语言的中的 try .... catch

看下实例代码:

package main

import (
    "fmt"
)

func main() {

    defer func() {
        fmt.Println("待处理的defer任务")
    }()

    fmt.Println("panic 前")
    panic("crash")
    fmt.Println("panic 后")
    
}

执行结果:

./prog.go:15:2: unreachable code
Go vet exited.

panic 前
待处理的defer任务
panic: crash

goroutine 1 [running]:
main.main()
    /tmp/sandbox675215325/prog.go:14 +0xb7

我们可以看到 "panic 前" 的信息打印成功, 但是 "panic 后" 的信息没有打印成功.
但是 defer 函数中的 "待处理的defer任务" 却打印成功了.
说明在 panic 触发时,它会一直等到当前协程上所有 defer 任务处理完成才退出程序.


recover修复错误

go 语言中提供的 recover 方法,用来修复错误,避免因为 panic 触发而导致整个程序退出.
但是: recover 使用有前提,必须在 defer 函数中才能使用 recover 方法.

通过上面关于 panic 触发会执行处理当前协程上 defer 任务, 而 recover 方法又只能在 defer 中运行,这样我们可以结合起来做一个错误处理方案.

package main

import (
    "fmt"
)

func done_recover() {
    defer func() {
        fmt.Println("defer func")
        if err := recover(); err != nil {
            fmt.Println("recover success")
        }
    }()

    arr := []int{1, 2, 3}
    fmt.Println(arr[4])
    fmt.Println("after panic")
}

func main() {

    fmt.Println("执行 done_recover")
    done_recover()
    fmt.Println("domain end")
    
}

上面 main() 函数中 调用 done_recover() 函数;
done_recover 函数中定义了容放3个元素的 arr 切片, 但是我们打印第四个元素时,由于越界,触发 panic ,
但是 panic 在退出程序前需要处理当前协程上所有的 defer 任务,
所以开始执行 defer 函数;
defer 函数if 判断如果当前有捕捉错误,就用 recover 进行修复,修复完打印出 "recover success" 信息.

我们一起来看下最后程序运行的结果:

执行 done_recover
defer func
recover success
domain end

看上面结果,程序没有退出,
首先打印 main 入口函数信息 "执行 done_recover ",
接着进入 done_recover 函数开始执行,
在输出数组元素越界时 fmt.Println(arr[4]) ,
触发了 panic, 导致 fmt.Println("after panic") 没有执行,
panic 在退出程序前需要处理当前协程所有 defer,
所以执行 defer 时,我们利用 recover 来修复此错误,
修复成后 打印 "recover success" ,
接着把程序主动权交给 main 函数,这时程序已经正常,
main 函数接着往下走,继续输出了" domain end "

出自:go 语言中的错误捕捉 panic 以及 recover修复错误

回到顶部