Отключить все горутины

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