Last active
August 2, 2021 17:07
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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