Go 示例: 错误

在 Go 中,通过显式、独立的返回值来传达错误是一种惯用法。这与 Java 和 Ruby 等语言中使用的异常以及 C 中有时使用的重载单一结果/错误值形成对比。Go 的方法使人们很容易看到哪些函数返回错误,并使用与其他非错误任务相同的语言结构来处理它们。

有关更多详细信息,请参阅 errors 包 的文档和 这篇博文

package main
import (
    "errors"
    "fmt"
)

按照惯例,错误是最后一个返回值,类型为 error,这是一个内置接口。

func f(arg int) (int, error) {
    if arg == 42 {

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

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

错误位置的 nil 值表示没有错误。

    return arg + 3, nil
}

哨兵错误是一个预先声明的变量,用于表示特定的错误条件。

var ErrOutOfTea = fmt.Errorf("no more tea available")
var ErrPower = fmt.Errorf("can't boil water")
func makeTea(arg int) error {
    if arg == 2 {
        return ErrOutOfTea
    } else if arg == 4 {

我们可以用更高级别的错误包装错误以添加上下文。最简单的方法是在 fmt.Errorf 中使用 %w 动词。包装的错误会创建一个逻辑链(A 包装 B,B 包装 C,等等),可以使用 errors.Iserrors.As 等函数查询该链。

        return fmt.Errorf("making tea: %w", ErrPower)
    }
    return nil
}
func main() {
    for _, i := range []int{7, 42} {

if 行中使用内联错误检查很常见。

        if r, e := f(i); e != nil {
            fmt.Println("f failed:", e)
        } else {
            fmt.Println("f worked:", r)
        }
    }
    for i := range 5 {
        if err := makeTea(i); err != nil {

errors.Is 检查给定错误(或其链中的任何错误)是否与特定错误值匹配。这在处理包装或嵌套错误时特别有用,允许您识别链中特定错误类型或哨兵错误。

            if errors.Is(err, ErrOutOfTea) {
                fmt.Println("We should buy new tea!")
            } else if errors.Is(err, ErrPower) {
                fmt.Println("Now it is dark.")
            } else {
                fmt.Printf("unknown error: %s\n", err)
            }
            continue
        }
        fmt.Println("Tea is ready!")
    }
}
$ go run errors.go
f worked: 10
f failed: can't work with 42
Tea is ready!
Tea is ready!
We should buy new tea!
Tea is ready!
Now it is dark.

下一个示例:自定义错误