To ensure Goroutines complete within a specified timeout in Go, you can use the context
package and the sync
package. Here's an example of how you can achieve this:
package main
import (
"context"
"fmt"
"sync"
"time"
)
func main() {
// Create a context with a timeout of 3 seconds
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// Create a WaitGroup to wait for all Goroutines to finish
var wg sync.WaitGroup
// Add the number of Goroutines to the WaitGroup
wg.Add(2)
// Start Goroutines
go worker(ctx, "Worker 1", &wg)
go worker(ctx, "Worker 2", &wg)
// Wait for all Goroutines to finish or timeout
go func() {
wg.Wait()
cancel()
}()
// Wait for the context to finish (either timeout or Goroutines finish)
<-ctx.Done()
// Check the reason for context cancellation
if ctx.Err() == context.DeadlineExceeded {
fmt.Println("Timeout exceeded")
} else {
fmt.Println("Goroutines finished")
}
}
func worker(ctx context.Context, name string, wg *sync.WaitGroup) {
defer wg.Done()
// Perform some task within the Goroutine
// ...
select {
case <-ctx.Done():
fmt.Printf("%s: %v\n", name, ctx.Err())
return
}
}
In this example, we create a context with a timeout of 3 seconds using context.WithTimeout
. We also create a sync.WaitGroup
to wait for all Goroutines to finish. We add the number of Goroutines to the WaitGroup
using wg.Add()
. Then, we start the Goroutines, passing the context and the WaitGroup
as parameters. Each Goroutine performs some task and checks for the cancellation of the context using a select statement on ctx.Done()
. If the context is cancelled, the Goroutine prints the reason for the cancellation and returns. After starting the Goroutines, we start another Goroutine that waits for all Goroutines to finish using wg.Wait()
and cancels the context using cancel()
. Finally, we wait for the context to finish using <-ctx.Done()
. If the context is cancelled due to the timeout, we print "Timeout exceeded". Otherwise, we print "Goroutines finished".