go 语言中的三种报错机制
-
第一种,也就是常说的 error 类型错误,不需要 recover 拯救,处理方式自己决定
-
第二种,panic 和 recover 是紧密集合的,有点类似 try catch,recover 能捕获到 panic
-
第三种,一些 Go 语言系统级别的错误,比如发生死锁,数据竞争,这种错误程序会立刻报错,无法 recover
作用
在 go
语言中,错误一般会由 error
触发,但是如果比较严重的错误(通常是没有恰当处理的 error
,也可是手动触发) 会造成 panic
。 一旦主程序 panic
,会导致整个程序挂掉。如果这个错误不是那么严重,我们希望程序可以继续往下执行,而不是整个程序挂掉。
- 用
recover
函数,对panic
错误进行拦截,避免上传给主函数,进而避免整个程序挂掉。 - 可以在程序崩溃前,做一些操作,举个例子,当 web 服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭,如果不做任何处理,会使得客户端一直处于等待状态。
下面例子
如果给 out 函数传入两个相同的形参,就会引发 panic
。
如果没有 recover
拦截,fmt.Print
这行是执行不到的。
func main() {
Out(1, 1)
fmt.Println("*******此行函数依然能继续执行******")
}
func Out(numb1, numb2 int) bool {
defer func() {
if r := recover(); r != nil {
fmt.Println("异常已扑捉,避免继续往上层传递")
}
}()
if numb1 == numb2 {
panic("两个数不能相等")
}
return numb1 > numb2
}
知识点
- recover 仅在延迟函数
defer
中有效 - 因为
Go
语言没有异常系统,其使用 panic 触发宕机类似于其他语言的抛出异常,recover 的宕机恢复机制就对应其他语言中的 try/catch 机制。
注意:即使是子协程内引发的 panic
依然会导致主程序的挂掉,如下面的例子
func main() {
go OutOne()
go OutTwo()
time.Sleep(time.Minute)
}
func OutOne() {
panic("错误")
}
func OutTwo() {
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
fmt.Print("****此处继续执行***")
}
}