Timeout for WaitGroup.Wait(): Idiomatic Approaches
In Go, a time limit can be set for WaitGroup.Wait() to prevent infinite waiting for errant workers. Here's a detailed exploration of idiomatic ways to implement it and alternative approaches.
Recommended Solution: Using a Timer and Channel
The following approach is widely considered the most idiomatic solution:
import (
"sync"
"time"
)
func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
c := make(chan struct{})
go func() {
wg.Wait()
close(c)
}()
select {
case <-c:
return false // completed normally
case <-time.After(timeout):
return true // timed out
}
}
Copy after login
- A channel (c) is created to signal when the wait group completes its wait.
- A goroutine is spawned to call wg.Wait() and close the channel when finished.
- A select statement listens for either the channel to be closed or a timeout to occur.
- If the channel is closed, the function returns false, indicating normal completion.
- If the timeout is reached, the function returns true, signifying a timeout.
Simplifying the Recommended Solution
For a simpler implementation, consider the following:
- Close the channel to signal completion instead of sending a value.
- Use defer to close the channel even if the function terminates prematurely.
- Remove the wait group if only one job needs to be waited for.
- Use time durations directly without conversions (e.g., time.Second).
Alternative Approach: Using a Cancellable Context
An alternative approach involves using a cancellable context:
import (
"context"
"sync/atomic"
"sync"
)
func waitWithCancel(ctx context.Context, wg *sync.WaitGroup) bool {
ctxDone := make(chan struct{})
var exited int32
go func() {
defer close(ctxDone)
wg.Wait()
atomic.StoreInt32(&exited, 1)
}()
select {
case <-ctx.Done():
return atomic.LoadInt32(&exited) == 0
case <-ctxDone:
return true
}
}
Copy after login
- A cancellable context (ctx) is created.
- A channel (ctxDone) is used to signal when the context is cancelled.
- A goroutine is spawned to wait for the wait group and signal the ctxDone channel.
- A select statement listens for either the context to be cancelled or the wait group to complete.
- If the context is cancelled, the function returns based on whether the wait group had already finished its wait.
The above is the detailed content of How to Implement a Timeout for WaitGroup.Wait() in Go?. For more information, please follow other related articles on the PHP Chinese website!