This seems to challenge my understanding of unbuffered channel, which is that it can only take one value and then it would block for a reader to read it.
- How in the following code
writeToChan
is able to write 3 values? - More so surprisingly, how are those values available to be read later albeit not in same order?
An excerpt from https://golang.org/doc/effective_go#channels
Receivers always block until there is data to receive. If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go writeToChan(ch)
go rdFrmChan(ch)
x := <- ch
fmt.Println("main read 1 -:",x)
fmt.Println("main read 2 -:",<-ch)
}
func writeToChan(c chan int) {
time.Sleep(time.Second * 1)
c <- 42
c <- 27
c <- 9
}
func rdFrmChan(c chan int) {
fmt.Println("Go routine read :", <-c)
}
Output:
Go routine read : 27
main read 1 -: 42
main read 2 -: 9
Playground link: https://play.golang.org/p/DYzfYh-kXnC
CodePudding user response:
Each line of the excerpt pasted is proven by your example code, if you understand the sequence of events happening.
After the goroutines are started, your main routine is blocked reading from the channel
c
, as it is yet to see a value to read. ThewriteToChan
routine waits for a second before writing the first value to the channelThe goroutine
rdFrmChan
is also blocked, because it is waiting to read on the channelch
After 1s, when the sleep on
writeToChan
expires, the first write (c <- 42
) will unblock your main routine first, causing the value to be stored inx
i.e. 42Next the
rdFrmChan
is unblocked on the next write to the channel (c <- 27
) and sees the value 27. The routine terminates at this point after printing the valueAt this point, there is only value to be written and one to be read. The third write (
c <- 9
) from the goroutine allows the main routine to read the value as part of<-ch
and print it