package errors import ( "errors" "fmt" "runtime" ) type ErrorWithStatus interface { error ExitStatus() int IsSkipPrintMessage() bool SetError(err error) ErrorWithStatus SkipMessage() ErrorWithStatus SetPrintMessage() ErrorWithStatus SetExitStatus(status int) ErrorWithStatus } type errorWithStatus struct { err error status int skipMessage bool frames []frame } type frame struct { file string line int function string } func NeedExit(err error) (ErrorWithStatus, bool) { if err != nil { if esw, ok := err.(ErrorWithStatus); ok { return esw, esw.ExitStatus() != 0 } } return nil, false } func NewErrorWithStatus(err error, status int, skipMessage bool) ErrorWithStatus { return &errorWithStatus{ err: err, status: status, skipMessage: skipMessage, } } func NewError() ErrorWithStatus { return &errorWithStatus{ err: errors.New("error"), status: -1, skipMessage: false, } } func NewErrorWithFrames(err error) ErrorWithStatus { pcs := make([]uintptr, 0) npc := runtime.Callers(0, pcs) returnValue := &errorWithStatus{ err: err, status: -1, skipMessage: false, } if npc > 0 { frs := runtime.CallersFrames(pcs) more := true var fr runtime.Frame for more { fr, more = frs.Next() returnValue.frames = append(returnValue.frames, frame{ file: fr.File, function: fr.Function, line: fr.Line, }) } } return returnValue } func NewErrorfStatus(status int, str string, v ...interface{}) ErrorWithStatus { return &errorWithStatus{ err: fmt.Errorf(str, v...), status: status, skipMessage: false, } } func NewErrorf(str string, v ...interface{}) ErrorWithStatus { return NewErrorfStatus(-1, str, v...) } func (e *errorWithStatus) Error() string { var s string for _, fr := range e.frames { s += fmt.Sprintf("\n%v", fr) } return e.err.Error() + s } func (e *errorWithStatus) ExitStatus() int { return e.status } func (e *errorWithStatus) IsSkipPrintMessage() bool { return e.skipMessage } func (e *errorWithStatus) SetError(err error) ErrorWithStatus { e.err = err return e } func (e *errorWithStatus) SkipMessage() ErrorWithStatus { e.skipMessage = true return e } func (e *errorWithStatus) SetPrintMessage() ErrorWithStatus { e.skipMessage = false return e } func (e *errorWithStatus) SetExitStatus(status int) ErrorWithStatus { e.status = status return e }