Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

go

channel

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?

like image 648
Matt Avatar asked Nov 18 '13 06:11

Matt


People also ask

What are the differences between unbuffered and buffered channels?

By default channels are unbuffered, which states that they will only accept sends (chan <-) if there is a corresponding receive (<- chan) which are ready to receive the sent value. Buffered channels allows to accept a limited number of values without a corresponding receiver for those values.

What are channels and Goroutines?

A goroutine is a function that runs independently of the function that started it. Sometimes Go developers explain a goroutine as a function that runs as if it were on its own thread. Channel is a pipeline for sending and receiving data. Think of it as a socket that runs inside your program.

How does channels work in Go?

In Golang, or Go, channels are a means through which different goroutines communicate. Think of them as pipes through which you can connect with different concurrent goroutines. The communication is bidirectional by default, meaning that you can send and receive values from the same channel.

What's the default buffer size of the channel in Go?

By default, a channel buffer size is 0 also called as unbuffered channel.


2 Answers

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.

like image 166
starrify Avatar answered Oct 27 '22 07:10

starrify


An unbuffered channel means that read and writes from and to the channel are blocking.

In a select statement:

  • the read would work if some other goroutine was currently blocked in writing to the channel
  • the write would work if some other goroutine was currently blocked in reading to the channel
  • otherwise the default case is executed, which happens in your case A.
like image 44
Simon Avatar answered Oct 27 '22 07:10

Simon