Errors {.en}

错误处理 {.zh}

::: {.en} In Go it’s idiomatic to communicate errors via an explicit, separate return value. This contrasts with the exceptions used in languages like Java and Ruby and the overloaded single result / error value sometimes used in C. Go’s approach makes it easy to see which functions return errors and to handle them using the same language constructs employed for any other, non-error tasks. :::

::: {.zh}

在 Go 中,通常用一个明确的,单独的返回值来传递错误信息。这与 Java 和 Ruby 等语言中使用的异常(exception)以及有时在 C 中使用的重载(overloaded)单返回/错误值有着明显不同。Go 的方法使得很容易看到哪些函数返回错误,并能像调用那些没有出错的函数一样调用。

:::

  1. package main
  2. import "errors"
  3. import "fmt"

::: {.en} By convention, errors are the last return value and have type error, a built-in interface. :::

::: {.zh}

按照惯例,错误是最后一个返回值,并且类型为 error,一个内建的接口。

:::

  1. func f1(arg int) (int, error) {
  2. if arg == 42 {

::: {.en} errors.New constructs a basic error value with the given error message. :::

::: {.zh}

errors.New 用给定的错误消息构造一个基本的 error 值。

:::

  1. return -1, errors.New("can't work with 42")
  2. }

::: {.en} A nil value in the error position indicates that there was no error. :::

::: {.zh}

返回错误值为 nil 表示没有错误。

:::

  1. return arg + 3, nil
  2. }

::: {.en} It’s possible to use custom types as errors by implementing the Error() method on them. Here’s a variant on the example above that uses a custom type to explicitly represent an argument error. :::

::: {.zh}

可以通过实现 Error() 方法来自定义 error 类型。以下是使用自定义错误类型显式表示上面示例中的参数错误。

:::

  1. type argError struct {
  2. arg int
  3. prob string
  4. }
  5. func (e *argError) Error() string {
  6. return fmt.Sprintf("%d - %s", e.arg, e.prob)
  7. }
  8. func f2(arg int) (int, error) {
  9. if arg == 42 {

::: {.en} In this case we use &argError syntax to build a new struct, supplying values for the two fields arg and prob. :::

::: {.zh}

在这个例子中,我们使用 &argError 语法来构建一个新结构体,为两个字段 argprob 提供值。

:::

  1. return -1, &argError{arg, "can't work with it"}
  2. }
  3. return arg + 3, nil
  4. }
  5. func main() {

::: {.en} The two loops below test out each of our error-returning functions. Note that the use of an inline error check on the if line is a common idiom in Go code. :::

::: {.zh}

下面的两个循环测试每个返回错误的函数。请注意,在 if 行内的错误检查是 Go 中的普遍用法。

:::

  1. for _, i := range []int{7, 42} {
  2. if r, e := f1(i); e != nil {
  3. fmt.Println("f1 failed:", e)
  4. } else {
  5. fmt.Println("f1 worked:", r)
  6. }
  7. }
  8. for _, i := range []int{7, 42} {
  9. if r, e := f2(i); e != nil {
  10. fmt.Println("f2 failed:", e)
  11. } else {
  12. fmt.Println("f2 worked:", r)
  13. }
  14. }

::: {.en} If you want to programmatically use the data in a custom error, you’ll need to get the error as an instance of the custom error type via type assertion. :::

::: {.zh}

你如果想在程序中使用一个自定义错误类型中的数据,你 需要通过类型断言来得到这个错误类型的实例。

:::

  1. _, e := f2(42)
  2. if ae, ok := e.(*argError); ok {
  3. fmt.Println(ae.arg)
  4. fmt.Println(ae.prob)
  5. }
  6. }
  1. $ go run errors.go
  2. f1 worked: 10
  3. f1 failed: can't work with 42
  4. f2 worked: 10
  5. f2 failed: 42 - can't work with it
  6. 42
  7. can't work with it

::: {.en} See this great post on the Go blog for more on error handling. :::

::: {.zh}

有关错误处理的更多信息,请参阅 Go 博客上的这篇 很棒的文章

:::