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.
2727package goutil
2828
2929import (
@@ -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.
3947var 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.
4654type 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.
5159func 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 .
6371func (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.
6981func 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.
88101type 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.
95108func 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.
107120func (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.
115133func 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