Middle
Kuidas õigesti lõpetada mitme goroutine'i täitmine Go-s?
sobes.tech AI
Vastus AI-lt
On olemas mitu levinud meetodit:
-
Konteksti kasutamine (Context): Soovitatav lähenemisviis operatsioonide tühistamiseks puustruktuuris. Konteksti saab edastada tühistamissignaalina kanali kaudu.
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Gorutina %d lõpetab: %v\n", id, ctx.Err()) return default: fmt.Printf("Gorutina %d töötab...\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() // Saada tühistamissignaal time.Sleep(1 * time.Second) // Anna aega gorutinatel lõpetada fmt.Println("Põhiprogramm on lõpetatud.") } -
Kanali kasutamine: Saates signaali (näiteks tühja struktuuri
struct{}) spetsiaalse kanali kaudu, saab teavitada gorutinat lõpetamisest.package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("Gorutina %d lõpetab kanali kaudu\n", id) return default: fmt.Printf("Gorutina %d töötab...\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) // Kanali sulgemine signaalib lõpetamist time.Sleep(1 * time.Second) // Anna aega gorutinatel lõpetada fmt.Println("Põhiprogramm on lõpetatud.") } -
Kasutades
sync.WaitGroup(ooteaeg, mitte signaal):WaitGroupkasutatakse gorutinate lõpetamise ootamiseks, kuid ise ei paku lõpetamise mehhanismi. Seda kasutatakse sageli koos konteksti või kanalitega.package main import ( "context" "fmt" "sync" "time" ) func worker(ctx context.Context, wg *sync.WaitGroup, id int) { defer wg.Done() // vähendab WaitGroupi loendurit, kui gorutina lõpeb for { select { case <-ctx.Done(): fmt.Printf("Gorutina %d lõpetab\n", id) return default: fmt.Printf("Gorutina %d töötab...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) var wg sync.WaitGroup numWorkers := 2 wg.Add(numWorkers) // seadistame WaitGroupi for i := 1; i <= numWorkers; i++ { go worker(ctx, &wg, i) } time.Sleep(3 * time.Second) cancel() // tühistamissignaal wg.Wait() // ootame kõigi gorutinate lõpetamist fmt.Println("Põhiprogramm on lõpetatud.") }
Valitud meetod sõltub konkreetsest kasutusjuhtumist ja gorutinate koostöö keerukusest. Kontekst on üldiselt eelistatud kaskadist tühistamiseks.