ГоЛанг правильный способ остановки гороутов

# #go #goroutine

Вопрос:

Шаблон Does для выбора выхода гарантирует, что все функции будут возвращены до завершения цикла.

Рассмотрим следующий код

 func FnBusy() {
    log.Println("Entering FnBusy")
    time.Sleep(1 * time.Minute)
    log.Println("Exiting FnBusy")
}

func TestGoRoutineStop(t *testing.T) {
    quit := make(chan interface{})
    wg := sync.WaitGroup{}
    ticker := time.NewTicker(10 * time.Millisecond)
    defer ticker.Stop()
    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            select {
            case <-quit:
                log.Println("Quit Called")
                return
            case <-ticker.C:
                FnBusy()
            }
        }
    }()

    time.Sleep(150 * time.Millisecond)
    close(quit)
    wg.Wait()

}
 

Когда я запускаю этот тест, я получаю следующий вывод

 === RUN   TestGoRoutineStop
2021/09/20 11:03:18 Entering FnBusy
2021/09/20 11:04:18 Exiting FnBusy
2021/09/20 11:04:18 Entering FnBusy
2021/09/20 11:05:18 Exiting FnBusy
2021/09/20 11:05:18 Entering FnBusy
2021/09/20 11:06:18 Exiting FnBusy
2021/09/20 11:06:18 Quit Called
--- PASS: TestGoRoutineStop (180.01s)
 

Что я хочу понять, так это когда close(quit) вызывается, и если FnBusy он все еще выполняется, будет ли он ждать завершения

Комментарии:

1. Гороутины выполняют код последовательно. case <- quit Путь к коду не будет выполняться во время FnBusy выполнения.

2. К вашему сведению — вставленный вами код не может выдать вставленный вами вывод, так как FnBusy он ожидает одну минуту, а подпрограмма в main ожидает 150 мс, цикл завершится после одного запуска FnBusy

3. @Inian Вполне вероятно, что тикер и канал выхода будут готовы во второй раз при выполнении инструкции select. Если выбор принимает регистр тикера, то FnBusy он будет выполнен дважды.