package errcode import ( "fmt" "runtime" "strconv" "strings" ) type errorWithCode struct { code int stack string msg string } func newErrorWithCode(code int, stack, msg string) *errorWithCode { return &errorWithCode{ code: code, stack: stack, msg: msg, } } func (e *errorWithCode) Error() string { return fmt.Sprintf("[stack ==> %v] code:%v msg:%v", e.stack, e.code, e.msg) } func New(code int, format string, args ...interface{}) error { return newError(code, 2, format, args...) } func ParseError(err error) (int, string, string) { if specErr, ok := err.(*errorWithCode); ok { return specErr.code, specErr.stack, specErr.msg } return ParseError(newError(ServerError, 3, err.Error())) } func newError(code int, callDeep int, format string, args ...interface{}) error { _, caller, line, ok := runtime.Caller(callDeep) if !ok { panic(ok) } tokens := strings.Split(caller, "/") if len(tokens) > 5 { tokens = tokens[len(tokens)-5:] } fileInfo := strings.Join(tokens, "/") err := newErrorWithCode(code, fileInfo+":"+strconv.Itoa(int(line)), fmt.Sprintf(format, args...)) return err }