Ինչպես ճիշտ ավարտել մի քանի goroutine-ների գործարկումը Go-ում?
sobes.tech AI
Պատասխան AI-ից
Կան մի քանի տարածված մեթոդներ.
-
Կոնտեքստի (Context) օգտագործում: Առաջարկվող մոտեցում է գործողությունների չեղարկման համար ծառային կառուցվածքում: Կոնտեքստը կարող է փոխանցել չեղարկման նշան՝ միջոցով ալիքի:
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Գործողությունը %d ավարտվում է՝ %v\n", id, ctx.Err()) return default: fmt.Printf("Գործողությունը %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() // Չեղարկման նշան ուղարկում time.Sleep(1 * time.Second) // ժամանակ տալ գործողություններին ավարտվելու fmt.Println("Հիմնական ծրագիրը ավարտվեց.") } -
Ճանալի օգտագործում: Ուղարկելով նշան (օրինակ՝ դատարկ կառուցվածք
struct{}) հատուկ ալիքի միջոցով, կարելի է տեղեկացնել goroutine-ին՝ անհրաժեշտության մասին՝ ավարտելու:package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("Goroutine %d ավարտվում է՝ ալիքի միջոցով\n", id) return default: fmt.Printf("Goroutine %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) // ալիքի փակումը նշում է ավարտը time.Sleep(1 * time.Second) // ժամանակ տալ goroutine-ներին ավարտելու fmt.Println("Հիմնական ծրագիրը ավարտվեց.") } -
sync.WaitGroupօգտագործում (սպասելու համար, ոչ նշան տալու համար):WaitGroup-ը օգտագործվում է խմբի goroutine-ների ավարտին սպասելու համար, բայց ինքնին չի ապահովում կանգնեցման մեխանիզմ: Այն հաճախ օգտագործվում է կոնտեքստի կամ ալիքների հետ համատեղ:package main import ( "context" "fmt" "sync" "time" ) func worker(ctx context.Context, wg *sync.WaitGroup, id int) { defer wg.Done() // նվազեցնում է `WaitGroup`-ի հաշվիչը ավարտին հասնելիս for { select { case <-ctx.Done(): fmt.Printf("Goroutine %d ավարտվում է\n", id) return default: fmt.Printf("Goroutine %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) // սկզբնականացման `WaitGroup` for i := 1; i <= numWorkers; i++ { go worker(ctx, &wg, i) } time.Sleep(3 * time.Second) cancel() // չեղարկման նշան wg.Wait() // սպասում է բոլոր goroutine-ների ավարտին fmt.Println("Հիմնական ծրագիրը ավարտվեց.") }
Ընտրությունը կախված է կոնկրետ օգտագործման դեպքից և goroutine-ների փոխազդեցության բարդությունից: Կոնտեքստը սովորաբար նախընտրելի է կասկադային չեղարկումների համար: