feat: error wrapper
This commit is contained in:
parent
a8310b5dc8
commit
d92cace9c8
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/errors.iml" filepath="$PROJECT_DIR$/.idea/errors.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1 @@
|
||||||
|
golang 1.16
|
|
@ -0,0 +1,131 @@
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestManual(t *testing.T) {
|
||||||
|
t.Logf("default: %v\n", NewError())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNeedExit(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
simpleCaseErr := NewError()
|
||||||
|
CaseNoExitErr := NewError().SetExitStatus(0)
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want ErrorWithStatus
|
||||||
|
want1 bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple",
|
||||||
|
args: args{
|
||||||
|
err: simpleCaseErr,
|
||||||
|
},
|
||||||
|
want: simpleCaseErr,
|
||||||
|
want1: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil input",
|
||||||
|
args: args{
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
want1: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not ErrorWithStatus",
|
||||||
|
args: args{
|
||||||
|
err: errors.New("test"),
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
want1: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error but no exit",
|
||||||
|
args: args{
|
||||||
|
err: CaseNoExitErr,
|
||||||
|
},
|
||||||
|
want: CaseNoExitErr,
|
||||||
|
want1: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, got1 := NeedExit(tt.args.err)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("NeedExit() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
if got1 != tt.want1 {
|
||||||
|
t.Errorf("NeedExit() got1 = %v, want %v", got1, tt.want1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewErrorWithFrames(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
simplecase := errors.New("test")
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want ErrorWithStatus
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{
|
||||||
|
name: "simple",
|
||||||
|
args: args{
|
||||||
|
err: simplecase,
|
||||||
|
},
|
||||||
|
want: NewErrorWithFrames(simplecase),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := NewErrorWithFrames(tt.args.err); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("NewErrorWithFrames() = %v, want %v", got, tt.want)
|
||||||
|
} else {
|
||||||
|
t.Log("check", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue