Sobes.tech
Senior

func main() { c := make(chan int, 1000) for i := 0; i < 100; i++ { go foo(c) } sum := 0 for r := range c { sum += r } fmt.Println(sum) } func foo(c chan int) { r := rand.Int() for i := 0; i < r; i++ { c <- r } } --- func main() { c := make(chan int, 1000) var wg sync.WaitGroup wg.Add(100) for i := 0; i < 100; i++ { go func() { defer wg.Done() foo(c) }() } go func() { wg.Wait() close(c) }() sum := 0 for r := range c { sum += r } // // fmt.Println(sum) } func foo(c chan int) { r := rand.Int() for i := 0; i < r; i++ { c <- r } }

sobes.tech AI

Պատասխան AI-ից

Նախորդ տարբերակում կա խնդիր՝ for r := range c ցիկլը անընդհատ սպասելու է, քանի որ ալիք c երբեք չի փակվում։ Դրա պատճառով ծրագիրը կկապվի։

Երկրորդ տարբերակում ավելացվել է sync.WaitGroup՝ սպասելու բոլոր գորուտինների ավարտին, և հետո ալիք c փակվում է։ Սա թույլ է տալիս ճիշտ դուրս գալ ալիքից ընթերցման ցիկլից։

Հիմնական կետեր՝

  • Օգտագործում sync.WaitGroup՝ բոլոր գորուտինների ավարտը հետևելու համար։
  • Ալիքը փակվում է բոլոր գորուտինների գրառումը ավարտելուց հետո։
  • for r := range c ցիկլը ավարտվում է, երբ ալիքը փակվում է։

Ներքևի կոդի ուղղված օրինակ՝

group := sync.WaitGroup{}
group.Add(100)
for i := 0; i < 100; i++ {
    go func() {
        defer group.Done()
        foo(c)
    }()
}
go func() {
    group.Wait()
    close(c)
}()

sum := 0
for r := range c {
    sum += r
}