Skip to content

Commit 2e4cdea

Browse files
lvan100lianghuan
authored andcommitted
111
1 parent 809a277 commit 2e4cdea

File tree

1 file changed

+40
-22
lines changed

1 file changed

+40
-22
lines changed

util/goutil/goutil.go

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
* limitations under the License.
1515
*/
1616

17-
/*
18-
Package goutil provides a safe way to execute goroutines with built-in panic recovery.
19-
20-
In practice, goroutines may panic due to issues like nil pointer dereference or out-of-bounds access.
21-
However, these panics can be recovered. This package offers a wrapper to safely run goroutines,
22-
ensuring that any panic is caught and passed to a user-defined `OnPanic` handler.
23-
24-
The `OnPanic` function allows developers to log the panic, report metrics, or perform other
25-
custom recovery logic, making it easier to manage and observe unexpected failures in concurrent code.
26-
*/
17+
// Package goutil provides safe goroutine utilities with built-in panic recovery.
18+
//
19+
// Goroutines may panic due to programming errors such as nil pointer dereference
20+
// or out-of-bounds access. Panics can be recovered without crashing the whole
21+
// process. This package offers wrappers to run goroutines safely and recover
22+
// from such panics.
23+
//
24+
// A global `OnPanic` handler is triggered whenever a panic is recovered. It allows
25+
// developers to log the panic, report metrics, or perform other custom recovery
26+
// logic, making it easier to monitor and debug failures in concurrent code.
2727
package goutil
2828

2929
import (
@@ -35,19 +35,27 @@ import (
3535
"github.com/go-spring/spring-base/util"
3636
)
3737

38-
// OnPanic is a global callback function triggered when a panic occurs.
38+
// OnPanic is a global callback function triggered whenever a panic is recovered
39+
// inside a goroutine launched by this package.
40+
//
41+
// By default it prints the panic value and stack trace to stdout.
42+
// Applications may override it during initialization to provide custom logging,
43+
// metrics, or alerting.
44+
//
45+
// Note: being global means it is shared across all usages. In testing
46+
// scenarios, remember to restore it after modification if necessary.
3947
var OnPanic = func(ctx context.Context, r any, stack []byte) {
4048
fmt.Printf("[PANIC] %v\n%s\n", r, stack)
4149
}
4250

4351
/********************************** go ***************************************/
4452

45-
// Status provides a mechanism to wait for a goroutine to finish.
53+
// Status provides a handle to wait for a goroutine to finish.
4654
type Status struct {
4755
wg sync.WaitGroup
4856
}
4957

50-
// newStatus creates and initializes a new Status object.
58+
// newStatus creates and initializes a new Status.
5159
func newStatus() *Status {
5260
s := &Status{}
5361
s.wg.Add(1)
@@ -59,13 +67,17 @@ func (s *Status) done() {
5967
s.wg.Done()
6068
}
6169

62-
// Wait waits for the goroutine to finish.
70+
// Wait blocks until the goroutine completes.
6371
func (s *Status) Wait() {
6472
s.wg.Wait()
6573
}
6674

67-
// Go runs a goroutine safely with context support and panic recovery.
68-
// It ensures the process does not crash due to an uncaught panic in the goroutine.
75+
// Go launches a goroutine that recovers from panics and invokes the global
76+
// OnPanic handler when a panic occurs.
77+
//
78+
// The provided context is passed to the goroutine function `f` and to OnPanic.
79+
// The goroutine does not stop automatically when the context is cancelled;
80+
// `f` should check `ctx.Done()` and return when appropriate.
6981
func Go(ctx context.Context, f func(ctx context.Context)) *Status {
7082
s := newStatus()
7183
go func() {
@@ -84,14 +96,15 @@ func Go(ctx context.Context, f func(ctx context.Context)) *Status {
8496

8597
/******************************* go with value *******************************/
8698

87-
// ValueStatus provides a mechanism to wait for a goroutine that returns a value and an error.
99+
// ValueStatus represents a goroutine that returns a value and an error.
100+
// It allows the caller to wait for the result.
88101
type ValueStatus[T any] struct {
89102
wg sync.WaitGroup
90103
val T
91104
err error
92105
}
93106

94-
// newValueStatus creates and initializes a new ValueStatus object.
107+
// newValueStatus creates and initializes a new ValueStatus.
95108
func newValueStatus[T any]() *ValueStatus[T] {
96109
s := &ValueStatus[T]{}
97110
s.wg.Add(1)
@@ -103,15 +116,20 @@ func (s *ValueStatus[T]) done() {
103116
s.wg.Done()
104117
}
105118

106-
// Wait blocks until the goroutine finishes and returns its result and error.
119+
// Wait blocks until the goroutine completes and returns its value and error.
107120
func (s *ValueStatus[T]) Wait() (T, error) {
108121
s.wg.Wait()
109122
return s.val, s.err
110123
}
111124

112-
// GoValue runs a goroutine safely with context support and panic recovery and
113-
// returns its result and error.
114-
// It ensures the process does not crash due to an uncaught panic in the goroutine.
125+
// GoValue launches a goroutine that executes the provided function `f`,
126+
// recovers from any panic, and invokes the global OnPanic handler.
127+
//
128+
// The context is passed to both `f` and OnPanic. The caller must ensure
129+
// that `f` observes `ctx.Done()` if early cancellation is desired.
130+
//
131+
// If a panic occurs, the recovered panic and stack trace are also reported
132+
// via OnPanic and wrapped into the returned error.
115133
func GoValue[T any](ctx context.Context, f func(ctx context.Context) (T, error)) *ValueStatus[T] {
116134
s := newValueStatus[T]()
117135
go func() {

0 commit comments

Comments
 (0)