Skip to content

Instantly share code, notes, and snippets.

@briansorahan
Last active August 2, 2021 17:07
Show Gist options
  • Save briansorahan/39372f6d7246fd5201cb325f41262690 to your computer and use it in GitHub Desktop.
Save briansorahan/39372f6d7246fd5201cb325f41262690 to your computer and use it in GitHub Desktop.
Demo errgroup.WithContext - one failed goroutine cancels the context that other goroutines are select'ing from
package main
import (
"context"
"fmt"
"os"
"time"
"golang.org/x/sync/errgroup"
)
func main() {
const numSuccess = 10
g, ctx := errgroup.WithContext(context.Background())
// Spin up some number of goroutines which will succeed.
// Then spin up one that will fail and *should* cancel the others via the context.
for i := 0; i < numSuccess; i++ {
j := i
g.Go(func() error {
return succeed(ctx, j, 10*time.Second)
})
}
g.Go(func() error {
return fail(ctx, 1*time.Second)
})
if err := g.Wait(); err == nil {
fmt.Fprintln(os.Stderr, "expected an error, got nil")
os.Exit(1)
}
}
func fail(ctx context.Context, delay time.Duration) error {
timeout := time.After(delay)
select {
case <-ctx.Done():
fmt.Println("context in goroutine canceled")
case <-timeout:
fmt.Println("failed goroutine timed out")
}
return fmt.Errorf("failed after %s", delay)
}
func succeed(ctx context.Context, i int, delay time.Duration) error {
timeout := time.After(delay)
select {
case <-ctx.Done():
fmt.Printf("context in goroutine %d canceled\n", i)
return nil
case <-timeout:
fmt.Printf("goroutine %d timed out\n", i)
return nil
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment