
Отключить все горутины
Сегодня мне нужно было решение для очистки и остановки всех горутин и ожидания их возврата. Я нашла в интернете разные шаблоны, но ничего не подошло. В случае необходимости я ищу чужую мудрость и ссылаюсь на официальные документы Go, блог и блог Дэйва Чейни.
После прочтения отличного поста Дейва Любопытные каналы я узнал, что закрытый канал никогда не блокируется, а канал с нулевым значением блокируется всегда. Это казалось началом решения! Я создал шаблон, чтобы блокировать return от выхода из каждой горутины. Затем, когда я готов вернуться от них, я закрываю () канал.
// Wait until the shutdownChan is closed <-shutdownChan return
Это, казалось, дало мне полпути, но я также хотел подождать, пока все горутины не будут закрыты, прежде чем продолжить. Пакет синхронизации был идеальным для этого. Создание группы ожидания (wg) и использование функции wg.Add(1) для каждой горутины. Суть в том, чтобы использовать defer wg.Done(), поэтому, когда канал закрывается и возвращается функция func, он уменьшает счетчик WaitGroup.
Поэтому, когда мне нужно закрыть все горутины, я закрываю (shutdownChan) и жду с помощью wg.Wait().
Вот шаблон: https://play.golang.org/p/zuwmSA1McA
package main
import (
“fmt”
“sync”
)
func main() {
wg := new(sync.WaitGroup)
shutdownChan := make(chan int)
// Let’s create 100 goroutines
for i := 0; i < 100; i++ {
fmt.Println(“creating goroutine”)
wg.Add(1)
go func(i int) {
defer wg.Done()
// Your code here
fmt.Println(“Do something here”)
// Wait until the shutdownChan is closed
<-shutdownChan
fmt.Printf(“%d goroutine shutdown \n”, i)
return
}(i)
}
close(shutdownChan)
wg.Wait()
fmt.Println(“All go routines shutdown.”)
}
В качестве эксперимента я сделал пакет, который делает это за вас. https://github.com/jesselucas/shutdown