Uber Go 语言编程规范:错误类型

在Golang中有多种声明错误的方式:

当返回错误时,请考虑以下内容以确定最佳选择:

  • 如果是一个简单的错误并且不需要额外的信息,那么 errors.New 就可以满足。
  • 如果客户端需要检测并且处理错误,那么你需要自定义一个错误类型,并且实现Error()方法。
  • 如果你需要传播下游函数返回的错误,那么你需要对此类错误进行相应的包装。
  • 其他情况,fmt.Errorf即可满足需求

如果客户端需要检测错误,并且您已经使用errors.New创建了一个简单的错误,请使用var定义有一个错误变量。

Bad

// package foo
//直接返回一个error
func Open() error {
  return errors.New("could not open")
}

// package bar

func use() {
  //直接返回一个错误
  if err := foo.Open(); err != nil {
  //通过的错误的描述信息进行判断
    if err.Error() == "could not open" {
      // handle
    } else {
      panic("unknown error")
    }
  }
}

Good

// package foo

//在foo包中,定义一个ErrCouldNotOpen 变量,并且此变量是可以导出的(首字母大写)
var ErrCouldNotOpen = errors.New("could not open")

func Open() error {
 //直接返回错误变量
  return ErrCouldNotOpen
}

// package bar
//在bar包中,
if err := foo.Open(); err != nil {
//根据变量类型进行判断
  if err == foo.ErrCouldNotOpen {
    // handle
  } else {
    panic("unknown error")
  }
}

如果你有一个错误,客户端可能需要进行检测判断,而且你期望还要添加更多的信息(例如,它不是一个静态的字符串),此种情况,你需要一个自定义的错误类型。

Bad

func open(file string) error {
//直接返回错误
  return fmt.Errorf("file %q not found", file)
}

func use() {
  if err := open("testfile.txt"); err != nil {
    //根据错误内容进行判断
    if strings.Contains(err.Error(), "not found") {
      // handle
    } else {
      panic("unknown error")
    }
  }
}

Good

//自定义一个错误类型
type errNotFound struct {
  file string
}

//实现Error()方法
func (e errNotFound) Error() string {
  return fmt.Sprintf("file %q not found", e.file)
}

//直接返回自定义的错误类型,并且实时修改错误内容
func open(file string) error {
  return errNotFound{file: file}
}

func use() {
  if err := open("testfile.txt"); err != nil {
    //通过类型断言
    if _, ok := err.(errNotFound); ok {
      // handle
    } else {
      panic("unknown error")
    }
  }
}

在直接导出自定义错误类型时要小心,因为它们已成为包的公共API的一部分。稳妥的办法是是公开匹配器函数,来鉴别错误类型。

// package foo
//在 foo 包中,自定义错误类型
type errNotFound struct {
  file string
}

//实现Error()方法
func (e errNotFound) Error() string {
  return fmt.Sprintf("file %q not found", e.file)
}

//类型断言
func IsNotFoundError(err error) bool {
  _, ok := err.(errNotFound)
  return ok
}

//返回错误
func Open(file string) error {
  return errNotFound{file: file}
}


// package bar
// 在 bar 包中,调用foo包中导出的方法
if err := foo.Open("foo"); err != nil {
  if foo.IsNotFoundError(err) {
    // handle
  } else {
    panic("unknown error")
  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamCatcher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值