diff --git a/recovery/recovery.go b/recovery/recovery.go new file mode 100644 index 00000000..b94d6783 --- /dev/null +++ b/recovery/recovery.go @@ -0,0 +1,47 @@ +package recovery + +type options struct { + handler func(err interface{}) +} + +type Option func(o *options) + +func WithHandler(handler func(err interface{})) Option { + return func(o *options) { + o.handler = handler + } +} + +type Recovery struct { + opt *options +} + +func New(opts ...Option) *Recovery { + o := &options{} + + for _, opt := range opts { + opt(o) + } + + if o.handler == nil { + o.handler = func(err interface{}) { + panic(err) + } + } + + return &Recovery{ + opt: o, + } +} + +func (r *Recovery) Wrap(f func() error) error { + defer func() { + if err := recover(); err != nil { + if r.opt.handler != nil { + r.opt.handler(err) + } + } + }() + + return f() +} diff --git a/recovery/recovery_test.go b/recovery/recovery_test.go new file mode 100644 index 00000000..15e5be48 --- /dev/null +++ b/recovery/recovery_test.go @@ -0,0 +1,28 @@ +package recovery + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRecovery_Wrap(t *testing.T) { + fn := func() error { + panic("test") + + return nil + } + + // default + r := New() + assert.Panics(t, func() { + _ = r.Wrap(fn) + }) + + // with handler + r = New(WithHandler(func(err interface{}) { + assert.Equal(t, "test", err) + })) + + assert.NoError(t, r.Wrap(fn)) +}