请教一个goroutine报错问题,在《Go语言高级编程》有个并行版的素数筛子的例子,我想让主程序结束的时候,释放每个筛子所在的管道(资源),修改成如下代码,但是运行会有错误发生,意思是管道关闭后,又执行了写操作,但是不太清楚,为什么会发生这种情况,代码如下,请大牛分析一下原因是什么?
```go
package prime
import (
"bytes"
"fmt"
"runtime"
"strconv"
"sync"
)
var wg1 = sync.WaitGroup{}
var chexit = make(chan bool)
func gen(name string) chan int {
ch := make(chan int)
wg1.Add(1)
go func() {
for i := 2; ; i++ {
select {
case ch <- i:
case <-chexit:
close(ch)
fmt.Println("go routine exit:", name)
wg1.Done()
return
}
}
}()
return ch
}
func primeFilter(chin chan int, prime int, name string) chan int {
chout := make(chan int)
wg1.Add(1)
go func() {
for {
select {
case v := <-chin:
if v%prime != 0 {
chout <- v
}
case <-chexit:
close(chout)
fmt.Println("go routine exit:", name)
wg1.Done()
return
}
}
}()
return chout
}
func Prime() {
ch := gen("generate numbers")
for i := 0; i < 100; i++ {
v := <-ch
//log.Printf("%d,%d\n", i+1, v)
ch = primeFilter(ch, v, "filter "+strconv.Itoa(i))
}
close(chexit)
wg1.Wait()
}
```
你上个筛子的chout作为下个筛子的chin,就会出现上个筛子协程中 chout <- v 执行先于下个筛子协程中v := <-chin操作,和close无关
#3
更多评论
chout无缓冲区,可能会出现 chout <- v 先于v := <-chin ,即写先于读情况
chout := make(chan int,100)
#1
但是每个筛子的写入chout都是在同一个goroutine中,而每个goroutine中的select 保证了要么执行 case v := <-chin:,要么执行case <-chexit:然后close(chout),下一个筛子都是读chout的操作,是不影响才对
#2