Collecting results
- Go course
- Intermediate
- Lesson 27/80
- 6 min
Collect results from a separate channel.
Collecting results
The number of results isn't always known. A sturdier way: track the workers with a sync.WaitGroup and close the result channel when all are done. Then the collecting side can use range:
var wg sync.WaitGroup
for w := 0; w < n; w++ {
wg.Add(1)
go func() { defer wg.Done(); isci(isler, sonuclar) }()
}
go func() { wg.Wait(); close(sonuclar) }()
for s := range sonuclar { ... }Order and mapping
Results from concurrent workers arrive in random order. If input order matters, either send the result with its job ID and write it at that index in a slice, or sort the results afterwards:
out := make([]int64, len(dosyalar))
for s := range sonuclar {
out[s.IsID] = s.Boyut
}Practice Ordered collection
Each of four jobs (ID 0–3) produces ID * 10. Use two workers, track completion with a WaitGroup, close the result channel and write results into a slice in ID order. Print the slice.
Starter code
package main
import (
"fmt"
"sync"
)
func main() {
// buraya yaz
}Sample solution
package main
import (
"fmt"
"sync"
)
type Sonuc struct{ ID, Deger int }
func main() {
isler := make(chan int)
sonuclar := make(chan Sonuc)
var wg sync.WaitGroup
for w := 0; w < 2; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for id := range isler {
sonuclar <- Sonuc{id, id * 10}
}
}()
}
go func() {
for i := 0; i < 4; i++ {
isler <- i
}
close(isler)
}()
go func() {
wg.Wait()
close(sonuclar)
}()
out := make([]int, 4)
for s := range sonuclar {
out[s.ID] = s.Deger
}
fmt.Println(out)
}Expected output
[0 10 20 30]
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Why is <code>wg.Add(1)</code> called <strong>before</strong> the goroutine instead of inside it?
- So Done is called automatically
- So Wait doesn't run before Add and return early Correct answer
- Because it's shorter
- Add doesn't work inside a goroutine
Explanation: If Wait runs before the goroutine starts, the counter looks like zero and Wait returns immediately; Add must happen first.
2 Wait for all
go func() {
wg.____()
close(sonuclar)
}()
go func() {
wg.Wait()
close(sonuclar)
}()
Explanation: Wait blocks until every worker calls Done; then the result channel closes safely.
3 Tool
| Term | Meaning |
|---|---|
wg.Add(1) |
Before the goroutine |
defer wg.Done() |
When the worker ends |
wg.Wait + close |
Close the result channel |
out[s.IsID] |
Keep input order |