Go Error处理
错误
在go中,错误是可以被接受的,一般把错误返回给函数调用者,由函数调用者自行决定如何处理错误。
如Atoi函数的例子。
func Atoi(s string) (int, error) {
// ... 省略
return int(i64), err
}
// 使用模式
func main() {
i,err:=strconv.Atoi("a")
if err!=nil {
fmt.Println(err)
}else {
fmt.Println(i)
}
}
error工厂函数
通过工厂函数创建一个error
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
error断言
将error接口类型强转成更加携带了更多错误信息的子类类型
sum, err := add(-1, 2)
if cm,ok:=err.(*commonError);ok{ // 进行错误断言
fmt.Println("错误代码为:",cm.errorCode,",错误信息为:",cm.errorMsg)
} else {
fmt.Println(sum)
}
错误嵌套
fmt.Errorf函数
假如我们现在要将一个基础error包装成一个信息更加多的errorPlus错误,我们可以
type errorPlus struct{
err error
msg string
}
以上方式实现了error的嵌套,但是这样的嵌套需要额外的编写代码,所以go提供了fmt.Errorf函数,来帮助我们进行Error嵌套。
func main() {
err := errors.New("I am base error")
err = fmt.Errorf("sub error xxx and base error msg is %w", err)
println(err.Error())
}
errors.Unwrap函数
取得套娃error的base error
func main() {
err := errors.New("I am base error")
err = fmt.Errorf("sub error xxx and base error msg is %w", err)
println(err.Error())
err = errors.Unwrap(err)
println(err.Error()) // I am base error
}
errors.Is函数
判断两个error是否具备嵌套关系.
errors.Is(A,B), 其实就是判断B是否在A的嵌套链当中,B的范围不能超过A。
func main() {
err := errors.New("I am base error")
errWarp := fmt.Errorf("sub error xxx and base error msg is %w", err)
println(errors.Is(err, errWarp)) // false
println(errors.Is(errWarp, err)) // true
}
errors.As函数
将base error转换成更具体的error
var cm *commonError
if errors.As(err,&cm){
fmt.Println("错误代码为:",cm.errorCode,",错误信息为:",cm.errorMsg)
} else {
fmt.Println(sum)
}
defer 关键字
defer关键字有点类似Java中的finally代码块,defer也是用来关闭资源的。
func main() {
defer func() {
println("one ")
}()
defer func() {
println("two ")
}()
defer func() {
println("three ")
}()
}
// 执行顺序. three two one
panic
一旦发生了panic,那么整个程序将无法继续运行,它的错误程度要比error深。我们可以自己抛出panic异常。
如果不影响程序的正常运行,使用error即可。
func main(){
// 一些逻辑
panic("this is pannic")
}
recover
recover可以拿到panic中的参数,recover一般和defer关键字搭配使用。
func main() {
defer func() {
if p:=recover();p!=nil{
fmt.Println(p)
}
}()
panic("some panic msg")
}