I came across this “puzzle” when I was studying termbox-go source code and I can’t wrap my head around it. So I wrote a very simple package to test it out. Run it in your head first before you scroll further for answer and my naive reasoning.
package mainimport "fmt"func foo(c chan int) {
a := 0
for {
select {
case c <- a:
a = <-c
fmt.Println("foo received", a)
}
}
}func main() {
c := make(chan int)
go foo(c) loop:
for {
select {
case r := <-c:
fmt.Println("main received", r)
c <- (r + 1) if r == 3 {
break loop
}
}
}
<-c
}
Please forgive this noob if you found this is too easy. I am not yet clock > 3 hours coding in GO yet, bear with me. So the answer is…
main received 0
foo received 1
main received 1
foo received 2
main received 2
foo received 3
main received 3
foo received 4
It was not obvious to me at the start when I was looking at the foo
's select
. I thought case c <- a
will be selected, based on the wrong assumption that c
channel is “empty” now and I can send 1 value inside. I pondered, searched, put more printf
and finally this answer from StackOverflow enlightened me. In short…
sends do not complete until there is a receiver to accept the value.
Love GO.