Middle
Ako správne ukončiť vykonávanie viacerých gorutín v Go?
sobes.tech AI
Odpoveď od AI
Existuje niekoľko bežných spôsobov:
-
Použitie kontextu (Context): Odporúčaný prístup na zrušenie operácií v stromovej štruktúre volaní. Kontext môže prenášať signál zrušenia cez kanál.
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Gorutina %d sa ukončuje: %v\n", id, ctx.Err()) return default: fmt.Printf("Gorutina %d pracuje...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) go worker(ctx, 1) go worker(ctx, 2) time.Sleep(3 * time.Second) cancel() // Odoslanie signálu zrušenia time.Sleep(1 * time.Second) // Dávame čas gorutinám na ukončenie fmt.Println("Hlavný program je ukončený.") } -
Použitie kanálov: Odoslaním signálu (napríklad prázdnej štruktúry
struct{}) cez špeciálny kanál možno oznámiť gorutine potrebu ukončenia.package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("Gorutina %d sa ukončuje cez kanál\n", id) return default: fmt.Printf("Gorutina %d pracuje...\n", id) time.Sleep(1 * time.Second) } } } func main() { stopChan := make(chan struct{}) go worker(stopChan, 1) go worker(stopChan, 2) time.Sleep(3 * time.Second) close(stopChan) // Zatvorenie kanála signalizuje ukončenie time.Sleep(1 * time.Second) // Dávame čas gorutinám na ukončenie fmt.Println("Hlavný program je ukončený.") } -
Použitie
sync.WaitGroup(na čakanie, nie na signalizáciu):WaitGroupsa používa na čakanie na dokončenie skupiny gorutín, ale sám o sebe neposkytuje mechanizmus na zastavenie. Často sa používa v kombinácii s kontextom alebo kanálmi.package main import ( "context" "fmt" "sync" "time" ) func worker(ctx context.Context, wg *sync.WaitGroup, id int) { defer wg.Done() // Znižuje čítač `WaitGroup` pri dokončení gorutiny for { select { case <-ctx.Done(): fmt.Printf("Gorutina %d sa ukončuje\n", id) return default: fmt.Printf("Gorutina %d pracuje...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) var wg sync.WaitGroup numWorkers := 2 wg.Add(numWorkers) // Inicializujeme `WaitGroup` for i := 1; i <= numWorkers; i++ { go worker(ctx, &wg, i) } time.Sleep(3 * time.Second) cancel() // Signál zrušenia wg.Wait() // Čakáme na dokončenie všetkých gorutín fmt.Println("Hlavný program je ukončený.") }
Voľba metódy závisí od konkrétneho prípadu použitia a zložitosti interakcií gorutín. Kontekst je všeobecne preferovaný pre kaskádové zrušenia.