包 github.com/pkg/errors
让开发人员很容易在 error
错误信息上带上堆栈信息,可以更快更准确定位错误,例如行号等信息。
如果项目代码比较复杂,且经常需要追踪 Bug,建议使用 github.com/pkg/errors
这个错误处理包。
安装
go get -v github.com/pkg/errors
这个包和标准库的 errors
包重名,并且都有 New()
函数,因此从标准库的错误处理方式转为带堆栈的错误处理上来还是比较方便的。下面代码使用 errors.Wrap()
函数对错误信息进行了包装:
package main
import (
"fmt"
"github.com/pkg/errors"
)
var ErrNameEmpty = errors.New("Name can't be empty!")
func (s *Student) SetName(newName string) (err error) {
if newName == "" || s.Name == "" {
return ErrNameEmpty
} else {
s.Name = newName
return nil
}
}
type Student struct {
Name string
Age int
}
func NewStu() (err error) {
stu := &Student{
Age: 19}
e := stu.SetName("")
if e != nil {
return errors.Wrap(e, "set name failed!")
} else {
return nil
}
}
func main() {
e := NewStu()
fmt.Printf("%+v\n", e)
}
最后通过 Printf()
,设置占位符 %+v
显示错误信息和堆栈信息,例如函数运行时的文件名、行数等信息,而占位符 %s
则只显示错误信息。
下面带堆栈信息的错误提示很容易让程序员定位问题发生的位置,比如 main.go:30
,表明在 main.go
文件的 30 行。
Name can't be empty!
main.init
main.go:9
runtime.main
/src/runtime/proc.go:189
runtime.goexit
/src/runtime/asm_amd64.s:1333
set name failed!
main.NewStu
main.go:30
main.main
main.go:38
runtime.main
/src/runtime/proc.go:201
runtime.goexit
/src/runtime/asm_amd64.s:1333
Wrap()
函数在已有错误基础上同时附加堆栈信息和新提示信息,WithMessage()
函数在已有错误基础上附加新提示信息,WithStack()
函数在已有错误基础上附加堆栈信息。在实际中可根据情况选择使用。
这个包比较简洁实用,而且有可能会纳入标准库,所以建议在实际生产中使用。
另外环境变量 GOTRACEBACK
对堆栈信息的输出信息量有较大影响,不同的值有不同详细程度的信息输出。
- GOTRACEBACK = none
- GOTRACEBACK = single(默认值)
- GOTRACEBACK = all
- GOTRACEBACK = system
- GOTRACEBACK = crash
在程序中 debug.SetTraceback (level string)
函数也可以设置该变量。