背景

go 的错误在一些场景上面的使用。

Errors

错误是通过返回一个 error 作为函数的额外返回值来表示的。如果返回 nil 意味着没有错误。
来源
通过调用 errors.New ,可以从字符串创建错误。

if failure {
	return errors.New("inverse tachyon pulse failed")
}

或者使用 fmt.Errorf

if failure {
	return fmt.Errorf("inverse tachyon pulse failed")
}

因为它们通常会在打印前加前缀,所以错误字符串不应该以大写字母开头

err := TryInverseTachyonPulse()
if err != nil {
	fmt.Printf("failed to solve problem: %s\n", err)
}

如果希望调用代码能够处理错误,则可以通过返回特殊值或新的类型来区分错误类型。
这时候只需要区分调用代码可以通过这种方式处理的差异,因为字符串允许通信错误的细节。
io.EOF 是一个特殊的值表示流的结束.你可以直接比较误差值 io.EOF
如果你想携带额外的错误数据,你可以使用一个新的类型

type ParseError struct {
	Line, Col int
}

func (p ParseError) Error() string {
	return fmt.Sprintf("parse error on line %d, column %d", p.Line, p.Col)
}

如果你想创建一个常量字符串错误,你可以使用一个命名类型string:

type errorConst string

const ErrTooManyErrors errorConst = "too many errors found."

func (e errorConst) Error() string {
	return string(e)
}

可以调用代码 switch 来判断不同类型的错误信息

switch err := err.(type) {
case ParseError:
	PrintParseError(err)
}

Naming 命名规则

错误类型以”Error”结束,错误的变量以”Err”或”Err”开头:

package somepkg

// ParseError is type of error returned when there's a parsing problem.
type ParseError struct {
  Line, Col int
}

var ErrBadAction = errors.New("somepkg: a bad action was performed")

// -----

package foo

func foo() {
    res, err := somepkgAction()
    if err != nil {
        if err == somepkg.ErrBadAction {
        }
        if pe, ok := err.(*somepkg.ParseError); ok {
             line, col := pe.Line, pe.Col
             // ....
        }
    }
}

总结

在处理不同错误的时候,在业务逻辑上,需要声明各个错误的内容,在使用上面和调度上需要注意好使用错误的规范,明确返回什么错误才能很好的进行错误的排除。避免因为错误内容的混淆导致无法找到问题的所在。