Middle
Kā pareizi pabeigt vairākas goroutines izpildi Go valodā?
sobes.tech AI
Atbilde no AI
Ir vairākas bieži sastopamas metodes:
-
Konteksta izmantošana (Context): Ieteicams pieeja operāciju atcelšanai koka struktūrā. Kontekstu var nodot atcelšanas signālam caur kanālu.
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Gorutina %d beigsies: %v\n", id, ctx.Err()) return default: fmt.Printf("Gorutina %d strādā...\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() // Nosūtīt atcelšanas signālu time.Sleep(1 * time.Second) // Dot laiku gorutinām pabeigties fmt.Println("Galvenā programma pabeigta.") } -
Kanālu izmantošana: Nosūtot signālu (piemēram, tukšu struktūru
struct{}) caur īpašu kanālu, var paziņot gorutīnai par nepieciešamību pabeigt.package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("Gorutina %d pabeigsies caur kanālu\n", id) return default: fmt.Printf("Gorutina %d strādā...\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) // Kanāla aizvēršana signālam par pabeigšanu time.Sleep(1 * time.Second) // Dot laiku gorutinām pabeigties fmt.Println("Galvenā programma pabeigta.") } -
Ar
sync.WaitGroupizmantošanu (gaidīšana pabeigšanai, nevis signāla sūtīšana):WaitGrouptiek izmantots, lai gaidītu grupas gorutīnu pabeigšanu, bet pats par sevi nesniedz apturēšanas mehānismu. To bieži izmanto kopā ar kontekstu vai kanāliem.package main import ( "context" "fmt" "sync" "time" ) func worker(ctx context.Context, wg *sync.WaitGroup, id int) { defer wg.Done() // samazina WaitGroup skaitītāju, kad gorutina pabeidzas for { select { case <-ctx.Done(): fmt.Printf("Gorutina %d pabeigsies\n", id) return default: fmt.Printf("Gorutina %d strādā...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) var wg sync.WaitGroup numWorkers := 2 wg.Add(numWorkers) // iestata WaitGroup for i := 1; i <= numWorkers; i++ { go worker(ctx, &wg, i) } time.Sleep(3 * time.Second) cancel() // atcelšanas signāls wg.Wait() // gaida visu gorutīnu pabeigšanu fmt.Println("Galvenā programma pabeigta.") }
Izvēlētais metode ir atkarīgs no konkrētā lietošanas gadījuma un gorutīnu mijiedarbības sarežģītības. Konteksts parasti ir ieteicams kaskadveida atcelšanai.