在 golang 的 defer 函数中的 recover() 只能捕获 panic, 不能捕获 error。如果发生 error, 后面的代码还会继续;如果发生 panic,后面的代码不会被执行。
func ErrorHandlingKeyPoint4Adv() (err error) {
fmt.Println("In the ErrorHandlingKeyPoint4Adv 想测试 recover 后再产生 error 怎么处理;" +
"后来精准发现 recover 只能捕获 panic, 不能捕获 error")
defer func() {
fmt.Printf("===In the defer func===\n")
// https://www.runoob.com/go/go-scope-rules.html
// 如果下面的代码走 case 1 即手动产生 error , 则 defer 函数里的 recover() 是不能捕获到该 error 的
// 如果下面的代码走 case 2 即手动产生 panic , 则 defer 函数里的 recover() 是会捕获 panic 的, 但是外层函数的调用者
// 只能获取到 the panic from the business code 而不是 the error from recover,因为这涉及到变量作用域的问题,
// if err := recover() 相当于定义了一个新的局部变量(注意写的是 :=),下面函数体里的
// err = errors.New("the error from recover") 相当于给该新局部变量赋值 不是 给函数返回值的 err 赋值;
// 你可能会想如果 不写 if err := recover() 写 if err = recover() 这样就给 函数返回值的 err 赋值了,
// 但这样会报赋值类型不对,因为 recover() 的返回值类型是 interface{} 不是 error 类型。
if err := recover(); err != nil {
fmt.Println("got the panic not error")
fmt.Println(err)
err = errors.New("the error from recover")
}
}()
fmt.Printf("For ErrorHandlingKeyPoint4Adv: test the panic\n")
// 感受 error 和 panic 的差异:
// Case 1:
// err = errors.New("the error from the business code")
// Case 2:
panic("the panic from the business code")
fmt.Printf("For ErrorHandlingKeyPoint4Adv: test the panic222\n")
return
}
对于 case 1 的运行结果:
In the ErrorHandlingKeyPoint4Adv 想测试 recover 后再产生 error 怎么处理;后来精准发现 recover 只能捕获 panic, 不能捕获 error
For ErrorHandlingKeyPoint4Adv: test the panic
For ErrorHandlingKeyPoint4Adv: test the panic222
===In the defer func===
the error from the business code
对于 case 2 的运行结果:
In the ErrorHandlingKeyPoint4Adv 想测试 recover 后再产生 error 怎么处理;后来精准发现 recover 只能捕获 panic, 不能捕获 error
For ErrorHandlingKeyPoint4Adv: test the panic
===In the defer func===
got the panic not error
the panic from the business code
<nil>