errors

package module
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2022 License: MIT Imports: 12 Imported by: 3

README

errors

errors 提供简单的错误处理。同时附带错误码映射, 与聚合错误切片。

CHANGELOG

CI/CD Release Go Reference Go Report Card codecov Github issues Github pull requests MIT

安装

go get github.com/eachinchung/errors

Documentation

Overview

Example (StackTrace)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func fn() error {
	e1 := errors.New("error")
	e2 := errors.Wrap(e1, "inner")
	e3 := errors.Wrap(e2, "middle")
	return errors.Wrap(e3, "outer")
}

func main() {
	type stackTracer interface {
		StackTrace() errors.StackTrace
	}

	err, ok := errors.Cause(fn()).(stackTracer)
	if !ok {
		panic("oops, err does not implement stackTracer")
	}

	st := err.StackTrace()
	fmt.Printf("%+v", st[0:2]) // top two frames

	// Example output:
	// github.com/eachinchung/errors_test.fn
	//         /Users/eachin/GolandProjects/errors/example_test.go:100
	// github.com/eachinchung/errors_test.ExampleStackTrace
	//         /Users/eachin/GolandProjects/errors/example_test.go:225
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func As

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

As 找到与目标匹配的错误链中的第一个 error, 如果是, 则将 target 设置为该 error 并返回 true。

该链由 error 组成, 然后是通过反复调用 Unwrap 获得的 error 序列。

如果 error 的具体值可分配给 target 指向的值, 或者如果 error 具有方法 As (interface{}) bool, 则 error 与 target 匹配, As(target) 返回 true。在后一种情况下, As 方法负责设定 target。

如果 target 不是指向实现 error 的类型或任何接口类型的非nil指针, As 将会 panic。如果错误为 nil, As 返回 false。

func Cause

func Cause(err error) error

Cause 如果可能的话, 返回 error 的根本原因 如果实现以下接口, 则 error 会返回原因:

type causer interface {
       Cause() error
}

如果 error 没有实现 Cause, 则返回原始 error。 如果 error 为 nil, 则将返回 nil, 而无需进一步调查。

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func fn() error {
	e1 := errors.New("error")
	e2 := errors.Wrap(e1, "inner")
	e3 := errors.Wrap(e2, "middle")
	return errors.Wrap(e3, "outer")
}

func main() {
	err := fn()
	fmt.Println(err)
	fmt.Println(errors.Cause(err))

}
Output:

outer: middle: inner: error
error
Example (Printf)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	err := errors.Wrap(func() error {
		return func() error {
			return errors.New("hello world")
		}()
	}(), "failed")

	fmt.Printf("%v", err)

}
Output:

failed: hello world

func Code

func Code(code int, message string) error

Code 用 message 注释错误, 同时用错误码映射错误

func Codef

func Codef(code int, format string, args ...interface{}) error

Codef 用格式化的 message 注释错误, 同时用错误码映射错误

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	var err error

	err = errors.Codef(1, "this is an error message")
	fmt.Println(err)

	err = errors.Wrap(err, "this is a wrap error message with error code not change")
	fmt.Println(err)

	err = errors.WithCodef(err, 3, "this is a wrap error message with new error code")
	fmt.Println(err)

}
Output:

this is an error message
this is a wrap error message with error code not change
this is a wrap error message with new error code
Example (Printf)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	var err error

	err = errors.Codef(1, "this is an error message")
	err = errors.Wrap(err, "this is a wrap error message with error code not change")
	err = errors.WithCodef(err, 3, "this is a wrap error message with new error code")

	fmt.Printf("%s\n", err)
	fmt.Printf("%v\n", err)
	fmt.Printf("%-v\n", err)
	fmt.Printf("%+v\n", err)
	fmt.Printf("%#v\n", err)
	fmt.Printf("%#-v\n", err)
	fmt.Printf("%#+v\n", err)

	// Example Output:
	// this is a wrap error message with new error code
	// this is a wrap error message with new error code - #2 [/Users/eachin/GolandProjects/errors/example_test.go:128 (github.com/eachinchung/errors_test.ExampleWithCode_printf)] (3) Encoding failed due to an error with the data
	// this is a wrap error message with new error code - #2 [/Users/eachin/GolandProjects/errors/example_test.go:128 (github.com/eachinchung/errors_test.ExampleWithCode_printf)] (3) Encoding failed due to an error with the data; this is a wrap error message with error code not change - #1 [/Users/eachin/GolandProjects/errors/example_test.go:127 (github.com/eachinchung/errors_test.ExampleWithCode_printf)] (1) 内部服务器错误; this is an error message - #0 [/Users/eachin/GolandProjects/errors/example_test.go:126 (github.com/eachinchung/errors_test.ExampleWithCode_printf)] (1) 内部服务器错误
	// [{"error":"Encoding failed due to an error with the data"}]
	// [{"caller":"#2 /Users/eachin/GolandProjects/errors/example_test.go:128 (github.com/eachinchung/errors_test.ExampleWithCode_printf)","code":3,"error":"this is a wrap error message with new error code","message":"Encoding failed due to an error with the data"}]
	// [{"caller":"#2 /Users/eachin/GolandProjects/errors/example_test.go:128 (github.com/eachinchung/errors_test.ExampleWithCode_printf)","code":3,"error":"this is a wrap error message with new error code","message":"Encoding failed due to an error with the data"},{"caller":"#1 /Users/eachin/GolandProjects/errors/example_test.go:127 (github.com/eachinchung/errors_test.ExampleWithCode_printf)","code":1,"error":"this is a wrap error message with error code not change","message":"内部服务器错误"},{"caller":"#0 /Users/eachin/GolandProjects/errors/example_test.go:126 (github.com/eachinchung/errors_test.ExampleWithCode_printf)","code":1,"error":"this is an error message","message":"内部服务器错误"}]
}
Output:

func Errorf

func Errorf(format string, args ...interface{}) error

Errorf 根据格式说明符进行格式化, 并将字符串作为 error 的值返回 Errorf 在它被调用的地方, 记录堆栈跟踪

Example (Extended)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	err := errors.Errorf("whoops: %s", "foo")
	fmt.Printf("%+v", err)

	// Example output:
	// whoops: foo
	// github.com/eachinchung/errors_test.ExampleErrorf_extended
	//         /Users/eachin/GolandProjects/errors/example_test.go:199
	// testing.runExample
	//         /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//         /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//         /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//         /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//         /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
}
Output:

func FilterOut

func FilterOut(err error, fns ...Matcher) error

FilterOut 从输入错误中删除与 Matcher 匹配的错误。 如果输入是非 Aggregate error, 则仅测试该错误。 如果输入 Aggregate error, 错误列表将被递归处理。

例如, 这可以用于从错误列表中删除已知的错误 (例如 io.EOF 或 os.PathNotFound )。

func Is

func Is(err, target error) bool

Is 报告错误链中的任何错误是否与目标匹配

该链由 error 组成, 然后是通过反复调用 Unwrap 获得的 error 序列。

如果一个 error 等于 target, 或者如果它实现了一个方法 is (error) bool 使得 is (target) 返回 true, 则认为该 error 与该 target 匹配。

func IsCode

func IsCode(err error, code int) bool

IsCode 报告err链中的任何错误是否包含给定的错误代码。

func MustRegister

func MustRegister(coder Coder)

MustRegister 注册用户定义错误代码。 当已存在相同的 code 时, 会发生 panic

func New

func New(message string) error

New 返回带有消息的 error New 在它被调用的地方, 记录堆栈跟踪

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	err := errors.New("whoops")
	fmt.Println(err)

}
Output:

whoops
Example (Printf)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	err := errors.New("whoops")
	fmt.Printf("%+v", err)

	// Example output:
	// whoops
	// github.com/eachinchung/errors_test.ExampleNew_printf
	//          /Users/eachin/GolandProjects/errors/example_test.go:17
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
}
Output:

func Register

func Register(coder Coder)

Register 注册用户定义错误代码。

func Unwrap

func Unwrap(err error) error

Unwrap 如果错误的类型包含一个 Unwrap 方法返回错误, 则返回该错误上的 Unwrap 方法的结果。 否则, Unwrap 返回 nil

func WithCode

func WithCode(err error, code int, message string) error

WithCode 返回 error, 该错误用 WithCodef 堆栈跟踪注释 err 同时用错误码映射错误, 并返回错误信息 如果 err 为 nil, 则 WithCodef 返回 nil

func WithCodef

func WithCodef(err error, code int, format string, args ...interface{}) error

WithCodef 返回 error, 该错误用 WithCodef 堆栈跟踪注释 err 同时用错误码映射错误, 并返回格式化错误信息 如果 err 为 nil, 则 WithCodef 返回 nil

func WithMessage

func WithMessage(err error, message string) error

WithMessage 用 message 注释错误 如果 err 为 nil, 则 WithMessage 返回 nil

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	cause := errors.New("whoops")
	err := errors.WithMessage(cause, "oh noes")
	fmt.Println(err)

}
Output:

oh noes: whoops

func WithMessagef

func WithMessagef(err error, format string, args ...interface{}) error

WithMessagef 用格式化的 message 注释错误 如果 err 为 nil, 则 WithMessagef 返回 nil

func WithStack

func WithStack(err error) error

WithStack 在调用堆栈时, 用堆栈跟踪注释 error 如果 err 为 nil, WithStack 返回 nil

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	cause := errors.New("whoops")
	err := errors.WithStack(cause)
	fmt.Println(err)

}
Output:

whoops
Example (Printf)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	cause := errors.New("whoops")
	err := errors.WithStack(cause)
	fmt.Printf("%+v", err)

	// Example Output:
	// whoops
	// github.com/eachinchung/errors_test.ExampleWithStack_printf
	//          /Users/eachin/GolandProjects/errors/example_test.go:55
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
	// github.com/eachinchung/errors_test.ExampleWithStack_printf
	//          /Users/eachin/GolandProjects/errors/example_test.go:56
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
}
Output:

func Wrap

func Wrap(err error, message string) error

Wrap 返回 error, 该错误用 Wrap 堆栈跟踪注释 err, 并返回提供错误信息 如果 err 为 nil, 则 Wrap 返回 nil

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	cause := errors.New("whoops")
	err := errors.Wrap(cause, "oh noes")
	fmt.Println(err)

}
Output:

oh noes: whoops
Example (Extended)
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func fn() error {
	e1 := errors.New("error")
	e2 := errors.Wrap(e1, "inner")
	e3 := errors.Wrap(e2, "middle")
	return errors.Wrap(e3, "outer")
}

func main() {
	err := fn()
	fmt.Printf("%+v\n", err)

	// Example output:
	// error
	// github.com/eachinchung/errors_test.fn
	//          /Users/eachin/GolandProjects/errors/example_test.go:100
	// github.com/eachinchung/errors_test.ExampleWrap_extended
	//          /Users/eachin/GolandProjects/errors/example_test.go:116
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
	// inner
	// github.com/eachinchung/errors_test.fn
	//          /Users/eachin/GolandProjects/errors/example_test.go:101
	// github.com/eachinchung/errors_test.ExampleWrap_extended
	//          /Users/eachin/GolandProjects/errors/example_test.go:116
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
	// middle
	// github.com/eachinchung/errors_test.fn
	//          /Users/eachin/GolandProjects/errors/example_test.go:102
	// github.com/eachinchung/errors_test.ExampleWrap_extended
	//          /Users/eachin/GolandProjects/errors/example_test.go:116
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
	// outer
	// github.com/eachinchung/errors_test.fn
	//          /Users/eachin/GolandProjects/errors/example_test.go:103
	// github.com/eachinchung/errors_test.ExampleWrap_extended
	//          /Users/eachin/GolandProjects/errors/example_test.go:116
	// testing.runExample
	//          /usr/local/opt/go/libexec/src/testing/run_example.go:64
	// testing.runExamples
	//          /usr/local/opt/go/libexec/src/testing/example.go:44
	// testing.(*M).Run
	//          /usr/local/opt/go/libexec/src/testing/testing.go:1505
	// main.main
	//         _testmain.go:91
	// runtime.main
	//          /usr/local/opt/go/libexec/src/runtime/proc.go:255
	// runtime.goexit
	//          /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1581
}
Output:

func Wrapf

func Wrapf(err error, format string, args ...interface{}) error

Wrapf 返回 error, 该错误用 Wrapf 堆栈跟踪注释 err, 并返回格式化错误信息 如果 err 为 nil, 则 Wrapf 返回 nil

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	cause := errors.New("whoops")
	err := errors.Wrapf(cause, "oh noes #%d", 2)
	fmt.Println(err)

}
Output:

oh noes #2: whoops

Types

type Aggregate

type Aggregate interface {
	error
	Errors() []error
	Is(error) bool
}

Aggregate 表示包含多个错误的对象, 但不一定具有单一的语义含义。 Aggregate 可以与 errors.Is() 一起使用, 以检查特定错误类型的发生。 errors.As() 不支持, 因为调用者可能关心与给定类型匹配的潜在多个特定错误。

func AggregateGoroutines added in v1.5.0

func AggregateGoroutines(funcs ...func() error) Aggregate

AggregateGoroutines 协程 error 收集器, 将所有非 nil error 填充到返回的 Aggregate 中。 如果所有函数均成功完成, 则返回 nil。

func Flatten

func Flatten(agg Aggregate) Aggregate

Flatten 将可能嵌套 Aggregate 的 Aggregate 全部递归地压平为一个 Aggregate。

func NewAggregate

func NewAggregate(errList ...error) Aggregate

NewAggregate 将 errList 转换为 Aggregate, Aggregate 本身就是 errors 接口的实现。 如果 slice 为空, 则返回 nil。 它将检查输入 errList 的任何元素是否为 nil, 以避免调用 Error() 时出现 nil panic。

type Coder

type Coder interface {
	// HTTPStatus 错误对应的HTTP状态码
	HTTPStatus() int

	// String 外部 (用户) 面对的错误信息
	String() string

	// Code 返回错误码
	Code() int
}

Coder 定义错误代码详细信息的接口。

func ParseCoder

func ParseCoder(err error) Coder

ParseCoder 将任何错误解析为 *withCode。 nil 错误将直接返回 nil。 没有 withStack 的错误, 将被解析为 ErrUnknown.

Example
package main

import (
	"fmt"

	"github.com/eachinchung/errors"
)

func main() {
	err := errors.Codef(3, "errors.ParseCoder")
	code := errors.ParseCoder(err)

	fmt.Println(err.Error())
	fmt.Println(code.Code())
	fmt.Println(code.String())
	fmt.Println(code.HTTPStatus())

}
Output:

errors.ParseCoder
3
encoding failed due to an error with the data
500

type Frame

type Frame uintptr

Frame represents a program counter inside a stack frame. For historical reasons if Frame is interpreted as a uintptr its value represents the program counter + 1.

func (Frame) Format

func (f Frame) Format(s fmt.State, verb rune)

Format formats the frame according to the fmt.Formatter interface.

%s    source file
%d    source line
%n    function name
%v    equivalent to %s:%d

Format accepts flags that alter the printing of some verbs, as follows:

%+s   function name and path of source file relative to the compile time
      GOPATH separated by \n\t (<funcname>\n\t<path>)
%+v   equivalent to %+s:%d

func (Frame) MarshalText

func (f Frame) MarshalText() ([]byte, error)

MarshalText formats a stacktrace Frame as a text string. The output is the same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.

type Matcher

type Matcher func(error) bool

Matcher 用于匹配 errors。如果 errors 匹配, 则返回true。

type StackTrace

type StackTrace []Frame

StackTrace is stack of Frames from innermost (newest) to outermost (oldest).

func (StackTrace) Format

func (st StackTrace) Format(s fmt.State, verb rune)

Format formats the stack of Frames according to the fmt.Formatter interface.

%s	lists source files for each Frame in the stack
%v	lists the source file and line number for each Frame in the stack

Format accepts flags that alter the printing of some verbs, as follows:

%+v   Prints filename, function, and line number for each Frame in the stack.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL