How does make(chan bool) behave differently from make(chan bool, 1)?

Matt picture Matt · Nov 18, 2013 · Viewed 8.6k times · Source

My question arises from trying to read a channel, if I can, or write it, if I can, using a select statement.

I know that channels specified like make(chan bool, 1) are buffered, and part of my question is what is the difference between that, and make(chan bool) -- which this page says is the same thing as make(chan bool, 0) --- what is the point of a channel that can fit 0 values in it?

See playground A:

chanFoo := make(chan bool)

for i := 0; i < 5; i++ {
    select {
    case <-chanFoo:
        fmt.Println("Read")
    case chanFoo <- true:
        fmt.Println("Write")
    default:
        fmt.Println("Neither")
    }
}

A output:

Neither
Neither
Neither
Neither
Neither

(Removing the default case results in a deadlock!!)

Now see playground B:

chanFoo := make(chan bool, 1)   // the only difference is the buffer size of 1

for i := 0; i < 5; i++ {
    select {
    case <-chanFoo:
        fmt.Println("Read")
    case chanFoo <- true:
        fmt.Println("Write")
    default:
        fmt.Println("Neither")
    }
}

B output:

Write
Read
Write
Read
Write

In my case, B output is what I want. What good are unbuffered channels? All the examples I see on golang.org appear to use them to send one signal/value at a time (which is all I need) -- but as in playground A, the channel never gets read or written. What am I missing here in my understanding of channels?

Answer

starrify picture starrify · Nov 18, 2013

what is the point of a channel that can fit 0 values in it

First I want to point out that the second parameter here means buffer size, so that is simply a channel without buffers (un-buffered channel).

Actually that's the reason why your problem is generated. Un-buffered channels are only writable when there's someone blocking to read from it, which means you shall have some coroutines to work with -- instead of this single one.

Also see The Go Memory Model:

A receive from an unbuffered channel happens before the send on that channel completes.