Я запускал следующий код на основе примера из книги «Параллелизм в Go», когда заметил, что не все закрывающие распечатки в конвейере печатаются.
Посмотрите, что «выполнено умножение!» отсутствует.
С другой стороны, NumGoroutine () показывает, что выполняется только основная функция.
Что не так со следующим кодом? (https://play.golang.org/p/tkFgvKboVgS)
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
generator := func(done <-chan struct{}) <-chan int {
intStream := make(chan int)
i:=0
go func() {
defer close(intStream)
for {
select {
case <-done:
fmt.Println("done generator!")
return
case intStream <- i:
time.Sleep(1 * time.Second)
i++
}
fmt.Println("generator after select")
}
}()
return intStream
}
multiply := func(
done <-chan struct{},
intStream <-chan int,
multiplier int,
) <-chan int {
multipliedStream := make(chan int)
go func() {
defer close(multipliedStream)
for i := range intStream {
select {
case <-done:
fmt.Println("done multiply !")
return
case multipliedStream <- i * multiplier:
}
fmt.Println("multiply after select")
}
}()
return multipliedStream
}
add := func(
done <-chan struct{},
intStream <-chan int,
additive int,
) <-chan int {
addedStream := make(chan int)
go func() {
defer close(addedStream)
for i := range intStream {
select {
case <-done:
fmt.Println("done add !")
return
case addedStream <- i + additive:
}
fmt.Println("add after select")
}
}()
return addedStream
}
done := make(chan struct{})
intStream := generator(done)
pipeline := add(done, multiply(done, intStream, 2), 2)
go func() {
time.Sleep(3 * time.Second)
close(done)
fmt.Println("Closed done")
}()
for v := range pipeline {
fmt.Println(v)
}
fmt.Println("finished iterating pipeline")
time.Sleep(10 * time.Second)
fmt.Println("ramaining goroutines:", runtime.NumGoroutine())
fmt.Println("finished!")
}
Выход:
add after select
2
multiply after select
generator after select
multiply after select
add after select
4
generator after select
multiply after select
add after select
6
generator after select
Closed done
multiply after select
done add !
finished iterating pipeline
generator after select
done generator!
ramaining goroutines: 1
finished!