Overview

errors包实现了处理错误函数的实现 New函数用于创建带文本消息上下文的错误 Unwrap,Is,As函数工作于封装了其他错误的errors,一个错误封装另一个错误,如果它含有下面的方法

Unwrap() error

如果e.Unwrap返回一个non-nil error w,则表示e封装了错误w Unwrap解包封装的错误,如果参数含有Unwrap方法,将会调用它,否则会返回nil 一个简单的方式创建封装的错误是调用 fmt.Errorf ,对错误参数应用%w动词
errors.Unwrap(fmt.Errorf("... %w ...", ..., err, ...))
return err
Is持续的解包第一个参数直到找到一个错误匹配第二个参数,它判断是否找到匹配,它应该比直接持续简单相等判断更优先使用:
if errors.Is(err, os.ErrExist)

优先于

if err == os.ErrExist

因为err封装了os.ErrExist这种比较将会成功

As持续的解包第一个参数直到找到一个错误能够被赋值给第二个参数(必须是指针),如果成功,则进行赋值并返回true,否则返回false 形式如下:
var perr *os.PathError
if errors.As(err, &perr) {
    fmt.Println(perr.Path)
}

优先于

if perr, ok := err.(*os.PathError); ok {
    fmt.Println(perr.Path)
}
因为这种形式将会成功如果错误封装了*os.PathError

函数(Functions)


func As(err error, target interface{}) bool


Example

package main

import (
	"errors"
	"fmt"
	"os"
)

func main() {
	if _, err := os.Open("non-existfile"); err != nil {
		var pathErr *os.PathError
		if errors.As(err, &pathErr) {
			fmt.Println("Failed at Path: ", pathErr.Path)
		} else {
			fmt.Println(err)
		}
	}
}

func Is(err, target error) bool


Example

package main

import (
	"errors"
	"io"
	"fmt"
)

type ReadAtEnd struct {
	id string
}
// 实现error interface
func (r *ReadAtEnd) Error() string {
	return fmt.Sprintf("%s: read at end", r.id)
}
func (r *ReadAtEnd) Unwrap() error {
	return io.EOF
}

func main() {
	var r *ReadAtEnd = &ReadAtEnd {
		id: "frist error",
	}
	if errors.Is(r, io.EOF) {
		fmt.Println("read at eof")
	} else {
		fmt.Println(r.Error())
	}
}

func New(text string) error

New函数返回一个有给定文本格式化的错误,每次调用New函数的错误都是有区别的,尽管它们有相同的文本

Example

package main
import (
	"fmt"
	"errors"
)

func main() {
	err := errors.New("random error")
	if err != nil {
		fmt.Print(err)
	}
}

func Unwrap(err error) error

解包错误