gracefull shutdown. Всегда ли будут завершаться горутины перед закрытием
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
)
const PROGRAMM_STOPPED_BY_USER = 100
func WriteInChannel(amountWorkers int) {
ctx := context.Background()
sigs := make(chan os.Signal, 1)
ch := make(chan int64, amountWorkers)
for {
for i := 0; i < amountWorkers; i++ {
ch <- time.Now().UnixNano()
go Worker(i, ch, ctx)
go captureSig(sigs)
}
time.Sleep(2 * time.Second)
}
}
func Worker(id int, ch <-chan int64, ctx context.Context) {
// reading channel and output data from it
for data := range ch {
fmt.Fprintln(os.Stdout, data, "(Worker ", id, ")")
}
}
func captureSig(sigs chan os.Signal) {
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
<-sigs
_, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
defer os.Exit(PROGRAMM_STOPPED_BY_USER)
log.Println("ALLDONE")
}
func write_and_read() {
var amountOfWorkers int
flag.IntVar(&amountOfWorkers, "a", 2, "-a <amount of workers>")
flag.Parse()
WriteInChannel(amountOfWorkers)
}
Никак не могу осилить логику gracefull завершения программы(горутин).
Погуглив я только больше запутываюсь и не могу ничего понять. Подскажите пожалуйста, как доработать этот код, чтобы он всегда завершал горутины прежде чем завершить программу. То есть нужно, чтобы os.Exit срабатывал когда все горутины завершены и кроме main ничего не выполняется.