Reading Concurrency in Go.
Trying to understand the or-done-channel pattern.
Having trouble wrapping my head around the execution flow.
I have mentioned number against the line where my doubt is from.
Why no return
statement in inner <-done
like we have in outer select
? Because of no return
statement, the next iteration will run and what if in that iteration we have both <- done
and <-c
available. We know select-case
will choose any of the case arbitrarily if multiple cases are available. Does this mean there is a possibility that <-c
will run even if <-done
was available?
Since select-case
arbitrarily chooses a case when multiple case are available, is it correct to assume that the <- done
will be chosen eventually but it is not necessary that it is chosen immediately as soon as it is closed. Of Course, this doubt is when both case i.e. <-done
and <-c
were available.
There is a possibility that <- v
is not written onto valStream
when done
is closed and it is lost forever, correct?
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
}
Basically, either correct me if I'm wrong or confirm that my understanding of the execution is correct. There indeed are "loopholes" with the code and that is just channel behaviour here.
Similar Question here
<-done
case should also have a return. This code is relying on the outer select to capture <-done
, which may not happen immediately<-done
is available it will be chosen eventually. It is likely that it will be chosen quickly, but you are correct. There is no guarantee that even if the inner select chooses <-done
, the outer will chose it as well in its next iteration.<-done
is available, then yes, there is a possibility that v
will be read but won't be written