【发布时间】:2019-12-29 20:07:57
【问题描述】:
当我注意到并非管道中的所有关闭打印都被打印时,我正在根据“Go 中的并发”一书中的示例运行以下代码。
看到“完成倍增!”不见了。
另一方面,NumGoroutine() 只显示 main func 正在运行。
以下代码有什么问题? (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!
【问题讨论】: