Go error使用

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Go error使用

Flappy   2022-06-02 我要评论

概述

当我们需要在Go项目中设计error,就不得不先知道Go error几种常用方法。标准库是一个非常好的学习方式,除此之外Go1.13的errors特性也需要掌握。

error使用方式

1.直接判等

这里的判等又分为变量判等和类型判等。
适用于pkg中预先定义好了多个error变量或类型,err只可能是这些变量的其中一个。
案例:os.IsExist(err)

// 变量判等
var errObj = errors.New(errObj)
func IsErrObj(err error) bool {
    return err == errObj
}
// 类型判等
type PathError struct {
   Op   string
   Path string
   Err  error
}
func IsPathError(err error) bool {
    switch e := err.(type) {
    case *PathError:
        return true
    default:
        return false
    }
} 

2.组合error接口,构建更强大的error接口

适用于构造pkg级别专用的error接口类型,同时在struct中组合Err变量表示底层错误
案例:net.Error interface

package net
type Error interface {
   error
   Timeout() bool   // Is the error a timeout?
   Temporary() bool // Is the error temporary?
}

type AddrError struct {
   Err  string
   Addr string
}

3.Errno模式

我们知道Linux有大量的错误码,表示了各种错误类型,对于很多系统而言错误码非常好用。Go如何兼容这种errono模式呢?
案例:sysacall.Errno

type Errno uintptr
func (e Errno) Error() string {
   if 0 <= int(e) && int(e) < len(errors) {
      s := errors[e]
      if s != "" {
         return s
      }
   }
   return "errno " + itoa.Itoa(int(e))
}

4.Go1.13的Wrap模式

在一些场景下,error是有链式关系的,我们固然可以自己实现一种链式error类型,但是Go1.13引入了语言级别的支持。它非常简单,只要3个重要的用法:

// 创建error
err2 := fmt.Errorf("%w", err1)
// 判断error链条中是否包含某个err变量
ok := errors.Is(err2, err1) // true
// 判断error链条中是否可赋值为某个err类型,成功则赋值给target
type Errno int
func (e *Errno) Error() string {
   return strconv.Itoa(int(*e))
}

func test() {
    var no = Errno(1)
    no1 := fmt.Errorf("%w", &no)
    no2 := fmt.Errorf("%w", no1)
    
    var target *Errno
    ok := errors.As(no2, target)
    fmt.Println(ok, target) // true, 1
}

以上代码都依赖 errors.Unwrap 函数,这个函数通过反射解析出链式error的上一个error。
从代码可以看出,error.Is 用于我们有2个err变量的情况下,判断前者是否链接了后者;
error.As 用于我们有一个err变量和一种error类型,想要判断链子中是否包含了这种error类型,如果是,我们顺带将值保存在target中,相当于丢弃了一些链式的信息,返璞归真。 这里有2个注意点:

  • Unwrap依赖反射,我们知道Go的反射是很慢的,所以需要考虑性能的场景慎用
  • As函数使用是,target本身必须是struct的指针类型,并且要取地址,否则可能会panic

5. Go版本低时的链式error

有时候我们会看到 github.com/pkg/errors 这个包,它其实就是老版本Go想要使用链式error所引用的包,它常用的方法是 Wrap 和 Cause,所以看到这2个函数就可以猜到一个项目没有使用新的errors特性。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们