Middle
Hogyan zárjuk le helyesen több goroutine futását Go-ban?
sobes.tech MI
Válasz az MI-től
Néhány gyakori módszer létezik:
-
A kontextus használata: Ajánlott megközelítés a műveletek törlésére a fastruktúrában. A kontextus jelet küldhet a csatornán keresztül.
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Goroutine %d befejeződik: %v\n", id, ctx.Err()) return default: fmt.Printf("Goroutine %d működik...\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() // A leállítási jel küldése time.Sleep(1 * time.Second) // Időt adunk a goroutine-oknak a befejezéshez fmt.Println("Fő program befejeződött.") } -
Csatornák használata: Egy speciális csatornára (pl. üres struktúra
struct{}) küldött jelzéssel jelezhető a goroutine-nak a befejezés szükségessége.package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("Goroutine %d a csatornán keresztül befejeződik\n", id) return default: fmt.Printf("Goroutine %d működik...\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) // A csatorna bezárása jelzi a befejezést time.Sleep(1 * time.Second) // Időt adunk a goroutine-oknak a befejezéshez fmt.Println("Fő program befejeződött.") } -
sync.WaitGrouphasználata (csak várakozásra, nem jelzésre): AWaitGroupa gorutinek befejezésének várására szolgál, de önmagában nem nyújt leállítási mechanizmust. Gyakran kontextussal vagy csatornákkal együtt használják.package main import ( "context" "fmt" "sync" "time" ) func worker(ctx context.Context, wg *sync.WaitGroup, id int) { defer wg.Done() // Csökkenti a WaitGroup számlálót a gorutine befejezésekor for { select { case <-ctx.Done(): fmt.Printf("Goroutine %d befejeződik\n", id) return default: fmt.Printf("Goroutine %d működik...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) var wg sync.WaitGroup numWorkers := 2 wg.Add(numWorkers) // Inicializáljuk a WaitGroup-ot for i := 1; i <= numWorkers; i++ { go worker(ctx, &wg, i) } time.Sleep(3 * time.Second) cancel() // A leállítási jel wg.Wait() // Várjuk, hogy minden goroutine befejeződjön fmt.Println("Fő program befejeződött.") }
A módszer választása az adott felhasználási esettől és a goroutine-ok közötti összetettségtől függ. Általában a contextet preferálják a láncolt leállásokhoz.