From 12fad19f7dd5390807a88286bd2b7e2b597bfc48 Mon Sep 17 00:00:00 2001 From: jizhuozhi Date: Fri, 19 Jul 2024 12:57:53 +0800 Subject: [PATCH] feat: recover panic and return as error --- api.go | 14 ++++++++++++-- api_test.go | 9 +++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/api.go b/api.go index 3e74f2d..370d9f2 100644 --- a/api.go +++ b/api.go @@ -3,13 +3,25 @@ package future import ( "context" "errors" + "fmt" + "runtime/debug" "sync/atomic" "time" ) +var ErrPanic = errors.New("async panic") +var ErrTimeout = errors.New("future timeout") + func Async[T any](f func() (T, error)) *Future[T] { s := &state[T]{} go func() { + defer func() { + if r := recover(); r != nil { + err := fmt.Errorf("%w, err=%s, stack=%s", ErrPanic, r, debug.Stack()) + var zero T + s.set(zero, err) + } + }() val, err := f() s.set(val, err) }() @@ -72,8 +84,6 @@ func AllOf[T any](fs ...*Future[T]) *Future[struct{}] { return &Future[struct{}]{state: s} } -var ErrTimeout = errors.New("future timeout") - func Timeout[T any](f *Future[T], d time.Duration) *Future[T] { ch := make(chan struct{}, 1) var val T diff --git a/api_test.go b/api_test.go index 0de9bfe..ab7ef69 100644 --- a/api_test.go +++ b/api_test.go @@ -22,6 +22,15 @@ func TestAsync(t *testing.T) { assert.Equal(t, nil, err) } +func TestAsyncPanic(t *testing.T) { + f := Async(func() (int, error) { + panic("panic") + }) + val, err := f.Get() + assert.Equal(t, 0, val) + assert.ErrorIs(t, err, ErrPanic) +} + func TestLazy(t *testing.T) { f := Lazy(func() (int, error) { return 1, nil