How does writing/reading multiple values to/from a unbuffered channel work in Go?

Issue

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.

  1. How in the following code writeToChan is able to write 3 values?
  2. 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

Solution

Each line of the excerpt pasted is proven by your example code, if you understand the sequence of events happening.

  1. 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. The writeToChan routine waits for a second before writing the first value to the channel

  2. The goroutine rdFrmChan is also blocked, because it is waiting to read on the channel ch

  3. 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 in x i.e. 42

  4. Next 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 value

  5. At 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

Answered By – Inian

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.