GO错误与异常处理
错误链与Is As
不同错误之间可以进行包操作来关联,整体为一个错误链。//代码12行,错误链(err21,err1)
错误链可以及unwrap操作进行解包。退出一个错误 //代码13,错误链(err1)
链条中的每个错误都有其类型 //代码30-33
errors.Is用来判断该错误链是否包含某个错误。 //代码21-23
errors.As用来判断错误链是否包含某类型错误。 //代码26-27
package main
import (
"fmt"
"errors"
"runtime/debug"
)
func main() {
err1 := fmt.Errorf("错误%d", 404) //普通错误,和new Error一样
err2 := fmt.Errorf("错误%d", 404) //即使err1一样但不是一个错误
err21 := fmt.Errorf("包裹%w", err1) // err21包裹err1错误
err1s := errors.Unwrap(err21) //解包回err1
fmt.Printf("类型:%T,值:%v\n", err1, err1)
fmt.Printf("类型:%T,值:%v\n", err2, err2)
fmt.Printf("类型:%T,值:%v\n", err21, err21)
fmt.Printf("类型:%T,值:%v\n", err1s, err1s)
//is判断错误是否包含该错误
fmt.Println(errors.Is(err21,err1))//true
fmt.Println(errors.Is(err21,err1s))//true
fmt.Println(errors.Is(err21,err2))//false err2并不等于err1
//as判断是否含有该错误类型
err3 := errors.New("xxx") //该错误和err1都是errors.errorString类型
fmt.Println(errors.As(err2,&err1))//true
fmt.Println(errors.As(err2,&err3))//true
}
//返回结果
类型:*errors.errorString,值:错误404
类型:*errors.errorString,值:错误404
类型:*fmt.wrapError,值:包裹错误404
类型:*errors.errorString,值:错误404
true
true
false
true
true
panic 和recover
panic和recover要在同一个协程使用。
panic抛出的内容会被recover捕获。
panic是异常不在业务代码里使用
//panic 触发异常(比较严重)可以被recover捕获
//panic 和recover要在一个协程内才行。
defer func() {
if e := recover(); e != nil {
// e 为 panic 返回的内容错误
fmt.Print(
fmt.Errorf("panic:%v\n%s", e, debug.Stack()),
)
}
}()
panic("危险")
//下面将不会执行
//....