როგორ სწორად დაასრულოთ რამდენიმე 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 * დროის სექუნდი) cancel() // გაუქმების სიგნალის გაგზავნა time.Sleep(1 * დროის სექუნდი) // გორუტინების დასრულების დროის მიცემა fmt.Println("ძირითადი პროგრამა დასრულდა.") } -
არხების გამოყენება: გაუქმების სიგნალის გასაგზავნად (მაგალითად, ცარიელი სტრუქტურა
struct{}) სპეციალურ არხზე, შეგვიძლია გორუტინს ვუთხრათ, რომ უნდა დასრულდეს.package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("გორუტინა %d დასრულდება არხით\n", id) return default: fmt.Printf("გორუტინა %d მუშაობს...\n", id) time.Sleep(1 * დროის სექუნდი) } } } func main() { stopChan := make(chan struct{}) go worker(stopChan, 1) go worker(stopChan, 2) time.Sleep(3 * დროის სექუნდი) close(stopChan) // არხის დახურვა სიგნალს აძლევს დასრულების შესახებ time.Sleep(1 * დროის სექუნდი) // გორუტინების დასრულების დროის მიცემა fmt.Println("ძირითადი პროგრამა დასრულდა.") } -
sync.WaitGroup-ის გამოყენება (დასრულების მოსალოდნელობისთვის, არა სიგნალისთვის):WaitGroupგამოიყენება გორუტინების დასრულების მოსალოდნელობისთვის, მაგრამ თავად არ უზრუნველყოფს გაჩერების მექანიზმს. ხშირად გამოიყენება კონტექსტთან ან არხებთან ერთად.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("გორუტინა %d დასრულდება\n", id) return default: fmt.Printf("გორუტინა %d მუშაობს...\n", id) time.Sleep(1 * დროის სექუნდი) } } } 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 * დროის სექუნდი) cancel() // გაუქმების სიგნალი wg.Wait() // ველით ყველა გორუტინის დასრულებას fmt.Println("ძირითადი პროგრამა დასრულდა.") }
შერჩევა მეთოდის დამოკიდებულია კონკრეტულ შემთხვევაზე და გორუტინების ურთიერთქმედების სირთულეზე. კონტექსტი ჩვეულებრივ სასურველია კასკადური გაუქმებისთვის.