Golang error 是一个包含了 Error() string 函数的接口,任何实现了 Error() string 的结构体都可以认为是 error 类型。
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
对于简单场景,返回一个带字符串描述的 error 可以通过 return errors.New("this is a err") 来实现。其内部实现的机制为:定义了一个 errorString 的结构体,调用 Error() 的时候返回初始化时传入的字符串。
// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
对于稍微复杂的场景,如果希望返回的错误信息中包含格式化字符串,可以通过 fmt.Errorf 来实现。其内部的实现为:通过一个 Printer 生成字符串,对于不包含异常的情况,调用上述的 errors.New。否则,返回一个 wrapError 结构体,保存包含的子 error ,并可以通过 Unwrap 取出。
func Errorf(format string, a ...any) error {
p := newPrinter()
p.wrapErrs = true
p.doPrintf(format, a)
s := string(p.buf)
var err error
if p.wrappedErr == nil {
err = errors.New(s)
} else {
err = &wrapError{s, p.wrappedErr}
}
p.free()
return err
}
type wrapError struct {
msg string
err error
}
func (e *wrapError) Error() string {
return e.msg
}
func (e *wrapError) Unwrap() error {
return e.err
}