吾八哥学Golang(十):Golang里的错误处理
错误处理是程序开发过程中一个很常见的动作,正确的处理程序的错误将会极大的提升问题故障排查的效率。Go语言通过内置的错误接口提供了非常简单的错误处理机制,下面简单的介绍相关的方法。
内置error包
error包定义
go里内置的error接口定义如下:
type error interface { Error() string }
errors包里的定义:
package errors // 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 }
定义非常简单,就是通过Error方法返回一个错误的string描述信息。
error使用方法
error通常用于某函数方法返回错误,而且大家都习惯的作为最后一个参数返回,下面看个简单使用例子:
package main import ( "errors" "fmt" ) func foo1(num int) error { if num >= 100 { return errors.New("只能传小于100的数字") } return nil } func main() { if err := foo1(1024); err != nil { fmt.Println(err) return } }
上面的函数用于判断传入的参数是否小于100,大于或等于100的时候就返回错误,返回的error错误可以使用fmt.Println进行打印出来。
自定义error类型
基于error类型的接口定义简单,我们也可以很方便的进行自定义error类型,只需要自定义类型里实现Error方法即可,下面的是自定义error实现方法以及用法:
package main import ( "fmt" ) type MyError struct { Num int Msg string } func (e *MyError) Error() string { return fmt.Sprintf("Num:%d, Msg: %s", e.Num, e.Msg) } func foo1(num int) error { if num >= 100 { return &MyError{ Num: num, Msg: "只能传小于100的数字", } } return nil } func main() { if err := foo1(1024); err != nil { fmt.Println(err) return } }
开源error包
内置的error包能处理一些简单的错误信息,往往在复杂的代码逻辑处理过程中,简单的错误信息不便于排除问题,比较多的开源的error包已经具备了这样的能力,例如:github.com/pkg/errors,该包具备输出堆栈的信息,有如下几个关键方法:
// 新生成一个带堆栈信息的错误 func New(message string) error // 附加信息 func WithMessage(err error, message string) error // 附加调用堆栈信息 func WithStack(err error) error // 同时附加堆栈和信息 func Wrap(err error, message string) error
这里使用Wrap方法来演示一个使用的例子:
package main import ( "fmt" "io/ioutil" "github.com/pkg/errors" ) func foo1() (string, error) { data, err := ioutil.ReadFile("test.data") if err != nil { return "", errors.Wrap(err, "读取文件失败") } return string(data), nil } func main() { str, err := foo1() if err != nil { fmt.Printf("%+v", err) return } fmt.Println(str) }
这里请注意,要打印出堆栈信息必须使用%+v,具体的区别为:
%s,%v 输出错误信息但不包含堆栈 %q 输出的错误信息带引号但不包含堆栈 %+v 输出错误信息和堆栈
上面的例子里返回的错误信息为: