diff --git a/README.md b/README.md index f4ec38e..07e4e1c 100644 --- a/README.md +++ b/README.md @@ -105,5 +105,32 @@ fmt.Println(cause) => password mismatch ``` +## Working with [Errors](https://blog.golang.org/go1.13-errors) package + +How to raise an `ApplicationError` with predefined error variables? + +``` +var ErrInvalidFormat = errors.New("[conf]invalid format") + +func ReadConfig() (*Config,error) { + //... + return nil, Throw(ErrInvalidFormat, cfgFile) + +} + +func main() { + +cfg, err := ReadConfig() + +if errors.Is(err, ErrInvalidFormat) { + panic(err) +} + +} + +``` + +See [Unit Tests](throw_test.go) for more examples. + diff --git a/throw.go b/throw.go new file mode 100644 index 0000000..5682671 --- /dev/null +++ b/throw.go @@ -0,0 +1,50 @@ +package errors + +import "strings" + +// ApplicationError an appliction error with predifined error variable and detail message +type ApplicationError struct { + // Inner inner error + Inner error + // MsgList detail message + MsgList []string +} + +// Error implement error.Error +func (e *ApplicationError) Error() string { + if e == nil { + return "" + } + + if e.Inner != nil && e.MsgList != nil { + return e.Inner.Error() + ": " + strings.Join(e.MsgList, " ") + } else if e.Inner != nil { + return e.Inner.Error() + } else { + return strings.Join(e.MsgList, " ") + } + +} + +// Unwrap implement error.Unwrap +func (e *ApplicationError) Unwrap() error { + if e == nil { + return nil + } + + if e.Inner != nil { + return e.Inner + } + + return e +} + +// Throw create an application error with prefinded error variable and message +// example +// errors.Throw(ErrInvalidParameter, "bloober_id is missing") +func Throw(inner error, msgList ...string) error { + return &ApplicationError{ + Inner: inner, + MsgList: msgList, + } +} diff --git a/throw_test.go b/throw_test.go new file mode 100644 index 0000000..0da1d2c --- /dev/null +++ b/throw_test.go @@ -0,0 +1,40 @@ +package errors + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestThrowIs(t *testing.T) { + + errIs := errors.New("Is") + + errIsNot := errors.New("Is not") + + err := Throw(errIs, "", "errors.Is works") + + require.ErrorIs(t, err, errIs) + require.Equal(t, false, errors.Is(err, errIsNot)) +} + +func TestThrowUnwrap(t *testing.T) { + + inner := errors.New("Inner") + + err := Throw(inner, "errors.Unwrap works") + + require.Equal(t, inner, errors.Unwrap(err)) +} + +func TestThrowAs(t *testing.T) { + + inner := errors.New("Inner") + + err := Throw(inner, "errors.As works") + + var appErr *ApplicationError + + require.Equal(t, true, errors.As(err, &appErr)) +}