Golang 的错误处理

在开始编写 Golang 代码之前, 先随便引入了一个 MYSQL 的包, 准备简单写写对数据库的操作.

但是刚一上手就发现一个问题, 如何处理引入包抛出的各种异常问题呢?

如何抛出一个错误

首先了解一下 error 类型:

1
2
3
type error interface  {
Error() string
}

创建 error 实例:

1
2
errors.New('Error Message')
fmt.Errorf('Invalid Number %g', f)

自定义 error 类型, 相当于实现了 error 接口:

1
2
3
4
5
6
7
type ParamError struct {
Name string
Line int
}
func (e *ParamError) Error() string {
return fmt.Sprintf("Param %s Invalid", e.Name)
}

如何处理错误

一般情况分为三种:

  1. 函数返回的错误: 使用特定值来判定函数执行状态.

    1
    2
    3
    4
    5
    6
    buf := make([]byte, 100)
    n, err := r.Read(buf)
    buf = buf[:n]
    if err == io.EOF {
    log.Fatal("read failed", err)
    }

    不建议使用, 因为这样判断可能增加包依赖, 项目大了会很难维护, 或者出现循环引用.

  2. 特定错误: 使用自定义类型, 上层使用断言.

    1
    2
    3
    4
    5
    6
    7
    8
    switch err := (interface{})(err).(type) {
    case nil:
    fmt.Println(val)
    case *MyError:
    fmt.Println("Error Happens ", err.Error())
    default:
    // unknown
    }
    1
    2
    3
    4
    5
    errMsg, ok := (interface{})(err).(*MyError)
    fmt.Printf("ok %v errMsg %s\n", ok, errMsg) // errMsg 由 Error() 方法返回.
    if ok {
    fmt.Println("Error is MyError type")
    }

    不建议使用, 每次都要使用别人的类来做判断, 耦合性高, 使接口脆弱.

  3. 不透明的错误处理: 获取到 nil 向下执行, 非 nil 当成未知错误无法处理直接向上抛出.

    1
    2
    3
    4
    5
    6
    7
    func foo() error {
    val, err := bar.Foobar()
    if err != nil {
    return err
    }
    // use val
    }

    这种是最好的方法.

一些特殊的情况

自定义一些更详尽有针对性的错误

有时直接 return err 会造成在顶部准备处理错误的时候, 发现错误并非能准确定位.
这时需要手动生成一些更有针对性的错误 return fmt.Errorf('auth failed: %v', err).

参考 github.com/pkg/errors 包, 打印出错误同时, 输出堆栈信息.

给错误自定义行为

给错误定义一些方法, 用这些方法实现错误的一些判断.

遇到错误不忽略, 不重复处理

参考文档

  1. 博客: https://ethancai.github.io/2017/12/29/Error-Handling-in-Go/
  2. 错误处理示例: https://github.com/EthanCai/goErrorHandlingSample
  3. The Go Blog
    1. Error handling in Go
    2. Defer, Panic, and Recover
  4. Dave Cheney
    1. presentation on my philosophy for error handling
    2. Don’t just check errors, handle them gracefully
    3. Stack traces and the errors package
  5. Go Packages
    1. errors
    2. runtime
  6. pkg: Artisanal, hand crafted, barrel aged, Go packages
    1. github.com/pkg/errors
Donate - Support to make this site better.
捐助 - 支持我让我做得更好.