英文:
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个主要选项:
-
基于字符串,即查看消息内容。当然,这种方法非常糟糕,因为如果以后更改消息中的一个字母,就需要重新编写所有的检查代码,所以我建议避免使用这种方法。
-
如果错误消息可以保持不变,可以简单地将错误作为全局变量创建,并将接收到的错误与已知的预定义错误进行比较。
例如:
var ErrDB = errors.New("数据库错误")
var ErrTimeout = errors.New("超时") //或其他错误
然后
if err := someFunc(); err != nil {
switch err {
case ErrDB:
//在这里执行需要执行的操作
case ErrTimeout:
//等等/等等
}
}
- 创建一个自定义的错误类型,因为错误只是接口,可以具有一些标识符或其他上下文数据。
例如:
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:
-
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.
-
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
}
}
- 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
....
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论