Search code examples
gochannelgoroutine

Is channel capacity necessary for range usage?


I am studying golang for some time. I encountered a problem with channels. I have 2 examples. They look same but 1 of them gives error. When i assign channel capacity(converting to a buffered channel) problem is being solved but other example has no capacity assignment.

This is my first question.

1st code https://play.golang.org/p/dbC7ZZsagin

// Creating a channel 
// Using make() function 
mychnl := make(chan string) 

// Anonymous goroutine 
go func() { 
    mychnl <- "GFG"
    mychnl <- "gfg"
    mychnl <- "Geeks"
    mychnl <- "GeeksforGeeks"
    close(mychnl) 
}() 

// Using for loop 
for res := range mychnl { 
    fmt.Println(res) 
} 

2nd code https://play.golang.org/p/yQMclmwOYs9

// We'll iterate over 2 values in the `queue` channel.
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)

// This `range` iterates over each element as it's
// received from `queue`. Because we `close`d the
// channel above, the iteration terminates after
// receiving the 2 elements.
for elem := range queue {
    fmt.Println(elem)
}

If you delete the capacity number at 2nd code, program won't work and I don't know why. I thought maybe for range iteration, it was necessary to assign a capacity value but there is another code which works.

Thanks from now.


Solution

  • Ranging over a channel does not require it to be buffered.

    Spec: Send statements:

    Communication blocks until the send can proceed. A send on an unbuffered channel can proceed if a receiver is ready.

    Your 2nd example:

    queue := make(chan string)
    queue <- "one"
    queue <- "two"
    

    If the queue channel is not buffered, the first send on it will block until there's another goroutine ready to receive from it. But there is only a single goroutine in your app, which would only start receiving from the channel after the sends: deadlock.

    When it has a buffer of 2, the channel can hold up to 2 values. So sending 2 values on it can proceed even if there is no one ready to receive from it. Sending a 3rd value would again block.

    Your first example works with unbuffered channel too because the sends and receives happen on 2 concurrent goroutines.