Go 1.x 没有结构化异常,使用 panic 抛出错误,recover 捕获错误。
Go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。
1) 假如函数F中书写了panic语句,会终止其后要执行的代码,在panic所在函数F内如果存在要执行的defer函数列表,按照defer的逆序执行
2) 返回函数F的调用者G,在G中,调用函数F语句之后的代码不会执行,假如函数G中存在要执行的defer函数列表,按照defer的逆序执行直到goroutine整个退出,并报告错误
1) 用来控制一个goroutine的panicking行为,捕获panic,从而影响应用的行为
2) 在defer函数中,通过recover来终止一个goroutine的panicking过程,从而恢复正常代码的执行, 可以获取通过panic传递的error
异常按照轻重可以分为error和painc, 其中painc是指不可修复性错误, error指之外的其他错误,
一般error可以忽略或者不处理, 但是painc必须处理。
package main
func main() {
task()
}
func task() {
defer func() {
if err := recover(); err != nil {
log.Error(err)
}
}()
panic("panic error!")
}
如果不想在每个task方法里面都写相同的defer, 可以简单封装一下
func main(){
var task2 = func() {
panic("bad exec params")
}
// 示例1: 普通方法调用
err := WithRecovery(task2, nil)
if err != nil {
fmt.Println(err)
}
// 示例2: 开新goroutine
go WithRecovery(task2, func(r interface{}) {
log.Error(context.Background(),
zap.Reflect("panic in the recoverable goroutine", r),
zap.Stack("panic stack info"),
)
})
}
// WithRecovery goroutine Recovery
// 如果没开新goroutine那么就直接用err
// 如果开新goroutine建议在recoverFn里面处理异常
func WithRecovery(execFunc func(), recoverFn func(r interface{})) (err error) {
defer func() {
if r := recover(); r != nil {
stackBuf := make([]byte, 1024)
n := runtime.Stack(stackBuf, false)
err = errors.New(fmt.Sprintf("panic: %v %s", err, stackBuf[:n]))
if recoverFn != nil {
recoverFn(r)
}
}
}()
execFunc()
return
}
需要注意的是 recover函数只能hold住当前goroutine的异常, 如果是从其他goroutine传递回来的它是hold不住的
func main() {
defer func() {
if e := recover(); e != nil {
log.Error(e)
}
}()
var wg sync.WaitGroup
wg.Add(1)
var task = func() {
// 这段注释后main函数会直接退出, 不会打印ok
/*defer func() {
if e := recover(); e != nil {
log.Error(e)
wg.Done()
}
}()*/
panic("bad exec params")
wg.Done()
}
go task()
wg.Wait()
fmt.Println("ok")
}
func main() {
handle err {
log.Fatal(err)
}
hex := check ioutil.ReadAll(os.Stdin)
}
该提案引入了两种新的语法形式,首先是 check
关键字,其可以选中一个表达式 check f(x, y, z)
或 check err
,其将会标识这是一个显式的错误检查。
其次引入了 handle
关键字,用于定义错误处理程序流转,逐级上抛,依此类推,直到处理程序执行 return
语句,才正式结束。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。