阅读Go 中的并发。
尝试理解或完成通道模式。
我无法理解执行流程。
我已经提到了我产生疑问的那条线上的数字。
为什么
return
inner 中没有<-done
像 outer 中那样的语句select
?因为没有return
语句,所以下一次迭代将运行,如果在该迭代中我们同时拥有<- done
和<-c
可用,会怎么样?我们知道select-case
如果有多个可用案例,我们将任意选择其中任何一种案例。这是否意味着<-c
即使<-done
可用,也有可能运行?由于
select-case
在有多个案件可用时任意选择一个案件,因此是否可以假设最终<- done
会选择,但不一定在结案后立即选择。当然,这种疑问是在两个案件即和都可用的情况下。<-done
<-c
有可能关闭时
<- v
不会写入并且会永远丢失,对吗?valStream
done
orDone := func(done, c <-chan interface{}) <-chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
select { //2
case <-done:
return
case v, ok := <-c:
if ok == false {
return
}
select {
case valStream <- v: //3
case <-done: //1
}
}
}
}()
return valStream
}
基本上,如果我错了,请纠正我,或者确认我对执行的理解是正确的。代码确实存在“漏洞”,这只是这里的渠道行为。
类似问题在这里
<-done
case 也应该有 return。此代码依赖于外部 select 来捕获<-done
,这可能不会立即发生<-done
可用,最终将选择它。很可能很快就会选择它,但您说得对。即使内部选择选择,也无法保证<-done
外部也会在下一次迭代中选择它。<-done
可用,那么是的,有可能v
会被读取但不会被写入