Code : https://play.golang.org/p/Oh3oTa7GIPX
type a struct {
c chan bool
}
func (a *a) do() {
a.c <- true
}
type b struct {
c chan bool
a a
}
func main() {
b := b{
c: make(chan bool),
a: a{c: make(chan bool)},
}
go b.s()
b.c <- true
// below is to stay main gorutine alive
done := make(chan bool)
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
for {
select {
case <-done:
fmt.Println("Done!")
return
}
}
}
func (b *b) s() {
for {
select {
case <-b.c:
fmt.Println("b c")
b.a.do()
case <-b.a.c:
fmt.Println("b a c")
}
}
}
Actual Output of above is
b c
Done!
Expected Ouput:
b c
b a c
Done !
I am not getting why is it not printing b a c
?
Code is self explanatory, if it still requires more details please ask
Your main
goroutine sends a value on b.c
, then waits:
b.c <- true
The goroutine you launch from main:
go b.s()
This is the one that receives from b.c
, and also from b.a.c
:
func (b *b) s() {
for {
select {
case <-b.c:
fmt.Println("b c")
b.a.do()
case <-b.a.c:
fmt.Println("b a c")
}
}
}
If a value is received from b.c
, this goroutine attempts to send on b.a.c
(in a.do()
method), and you expect this same goroutine to receive from b.a.c
. But since b.a.c
is unbuffered, the send will block, so it will never reach the next iteration in b.s()
where it could / would receive from b.a.c
.
If a channel is unbuffered, a send on it may only proceed if there is another goroutine ready to receive from it.
If you make the b.a.c
channel buffered, a send on it can proceed without blocking, so in the next iteration it can be received:
a: a{c: make(chan bool, 1)}
With this change you get your expected output. Try it on the Go Playground.