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 ничего не выполняется.


Ответы (0 шт):