主要目的是设置调试并使错误日志更有用,但这是一个很大的变化,所以我想知道:任何流行问题?
package main
import(
"errors"
//"fmt"
"runtime"
"github.com/fatih/structs"
"github.com/Sirupsen/logrus"
)
type Error interface {
Mapify() map[string]interface{}
Error() string
}
func New(err error) Error {
//get error runtime info
pc, file, line, _ := runtime.Caller(1)
funcName := runtime.FuncForPC(pc).Name()
return &ErrorString{err.Error(), file, funcName, line}
}
type ErrorString struct {
Err string
File string//file name
Func string//function name
Line int
}
func (s *ErrorString) Mapify() map[string]interface{} {
return structs.Map(s)
}
func (s *ErrorString) Error() string {
return s.Err
}
func main(){
logrus.WithFields(logrus.Fields(throw().Mapify())).Error(errors.New("test"))
}
func throw() Error{
return New(errors.New("any error"))
}
答案 0 :(得分:2)
您可以在项目youtube/vitess/go/tb/error.go
中看到类似的方法,但它会检查提供新错误的参数之一是否已包含堆栈:
func Errorf(msg string, args ...interface{}) error {
stack := ""
// See if any arg is already embedding a stack - no need to
// recompute something expensive and make the message unreadable.
for _, arg := range args {
if stackErr, ok := arg.(stackError); ok {
stack = stackErr.stackTrace
break
}
}
// compute own stack if empty
this gist中说明了另一种更简单的方法:获取现有错误(而不是定义新类型),并向其添加/打印堆栈信息。
// Handle an error for any function at <depth> from the top of the call stack
func HandleDepth(msg string, err error, depth int) {
// If the error is non-nil
if err != nil {
// Find out who called it and where from, skip the top <depth> calls
pc, file, line, ok := runtime.Caller(depth)
// Parse out the filename and calling function
filename := filepath.Base(file)
callingFunc := runtime.FuncForPC(pc)
callingFuncName := callingFunc.Name()
// If we could retrieve the information then print a message and exit with an error
if ok {
fmt.Printf("%s:%s:%d: %s %s\n", filename, callingFuncName, line, msg, err)
os.Exit(1)
}
}
}