Skip to content

Instantly share code, notes, and snippets.

@pteich pteich/main.go
Last active Sep 4, 2019

Embed
What would you like to do?
Example for using go's sync.errgroup together with signal detection signal.Notify to stop all running goroutines
package main
import (
"fmt"
"time"
"golang.org/x/sync/errgroup"
"context"
"os"
"syscall"
"os/signal"
)
func main() {
ctx, done := context.WithCancel(context.Background())
g, gctx := errgroup.WithContext(ctx)
// goroutine to check for signals to gracefully finish all functions
g.Go(func() error {
signalChannel := make(chan os.Signal, 1)
signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)
select {
case sig := <-signalChannel:
fmt.Printf("Received signal: %s\n", sig)
done()
case <-gctx.Done():
fmt.Printf("closing signal goroutine\n")
return gctx.Err()
}
return nil
})
// just a ticker every 2s
g.Go(func() error {
ticker := time.NewTicker(2 * time.Second)
for {
select {
case <-ticker.C:
fmt.Printf("ticker 2s ticked\n")
// testcase what happens if an error occured
//return fmt.Errorf("test error ticker 2s")
case <-gctx.Done():
fmt.Printf("closing ticker 2s goroutine\n")
return gctx.Err()
}
}
})
// just a ticker every 1s
g.Go(func() error {
ticker := time.NewTicker(1 * time.Second)
for {
select {
case <-ticker.C:
fmt.Printf("ticker 1s ticked\n")
case <-gctx.Done():
fmt.Printf("closing ticker 1s goroutine\n")
return gctx.Err()
}
}
})
// force a stop after 60s
time.AfterFunc(60 * time.Second, func() {
fmt.Printf("force finished after 60s")
done()
})
// wait for all errgroup goroutines
if err := g.Wait(); err == nil {
fmt.Println("finished clean")
} else {
fmt.Printf("received error: %v", err)
}
}
@otiai10

This comment has been minimized.

Copy link

commented Apr 23, 2018

saved my day

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.