吾八哥学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 输出错误信息和堆栈
上面的例子里返回的错误信息为:
