Отключить все горутины
Сегодня мне нужно было решение для очистки и остановки всех горутин и ожидания их возврата. Я нашла в интернете разные шаблоны, но ничего не подошло. В случае необходимости я ищу чужую мудрость и ссылаюсь на официальные документы 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