处理多个错误

huangapple go评论135阅读模式
英文:

Handling multiple errors

问题

我有一个Function1:

func Function1() {
    if err := Function2(); err != nil {
        
    }
}

还有一个Function2:

func Function2() error {
    if err := doSomethingThatMightCauseError(); err != nil {
        return errors.New("错误类型1")
    }

    if err := doSomethingElseThatMightCauseError(); err != nil {
        return errors.New("错误类型2")
    }
}

在Function1中,如何检测发生了什么类型的错误(内部错误、数据库中未找到结果等),然后相应地进行处理?

英文:

I have Function 1:

func Function1() {
    if err := Function2(); err != nil {
        
    }
}

and Function2:

func Function2() error {
    if err := doSomethingThatMightCauseError(); err != nil {
        return errors.New("Error Type 1")
    }

    if err := doSomethingElseThatMightCauseError(); err != nil {
        return errors.New("Error Type 2")
    }
}

How can I detect what type of error has happened (internal, no results found in db etc) and then handle accordingly in Function 1?

答案1

得分: 5

你有3个主要选项:

  1. 基于字符串,即查看消息内容。当然,这种方法非常糟糕,因为如果以后更改消息中的一个字母,就需要重新编写所有的检查代码,所以我建议避免使用这种方法。

  2. 如果错误消息可以保持不变,可以简单地将错误作为全局变量创建,并将接收到的错误与已知的预定义错误进行比较。

例如:

var ErrDB = errors.New("数据库错误")
var ErrTimeout = errors.New("超时") //或其他错误

然后

if err := someFunc(); err != nil {
  switch err {
  case ErrDB:
    //在这里执行需要执行的操作
  case ErrTimeout:
    //等等/等等
  }
}
  1. 创建一个自定义的错误类型,因为错误只是接口,可以具有一些标识符或其他上下文数据。

例如:

const (
  ErrDB = 1
  ErrTimeout = 2
  ...
)

type MyError struct {
   Code int
   Message string
}

// 这是必须要成为错误的函数
func (e MyError) Error() string {
   return e.Message
}


func NewError(s string, code int) error {
   return MyError{s, code}
}

然后在返回错误时,可以这样做:

// 返回一个具有数据库代码的MyError,用于数据库操作
func someFunc() error {
   if err := talkToDB(); err != nil {
      return NewError(err.Error(), ErrDB)
   }
   return nil
}

在分析错误时,可以这样做:

if err := someFunc(); err != nil {

   // 检查是否为MyError
   if me, ok := err.(MyError); ok {
     // 现在我们可以检查代码
     switch me.Code {
       case ErrDB:
         //处理这个错误
       ....
     }  
   }
}
英文:

You have 3 main options:

  1. string based, i.e. looking into the message. This is of course pretty bad because if you later change one letter in the message, you need to rewrite all the checking code, so I'd avoid it.

  2. If the error messages can stay constant, simply create errors as global variables, and then compare the received error with a known pre-defined one.

For example:

var ErrDB = errors.New("Database Error")
var ErrTimeout = errors.New("Timeout") //or whatever

and then

if err := someFunc(); err != nil {
  switch err {
  case ErrDB:
    //do stuff that needs to be done here
  case ErrTimeout:
    //etc /etc
  }
}
  1. Create a custom error type, since errors are just interfaces, that can have some identifier or other contextual data.

For example:

const (
  ErrDB = 1
  ErrTimeout = 2
  ...
)

type MyError struct {
   Code int
   Message string
}

// This is what you need to be an error
func (e MyError)Error() string {
   return e.Message
}


func NewError(s string, code int) error {
   return MyError{s,code}
}

and then when you return it do something like this:

// Return a MyError with a DB code for db operations
func someFunc() error {
   if err := talkToDB(); err != nil {
      return NewError(err.Error(), ErrDB)
   }
   return nil
}

and when analyzing it:

if err := someFunc(); err != nil {

   // check if this is a MyError
   if me, ok := err.(MyError); ok {
     // now we can check the code
     switch me.Code {
       case ErrDB:
         //handle this
       ....
     }  
   }
}

huangapple
  • 本文由 发表于 2015年5月22日 02:06:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/30381233.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定