Buffered / Unbuffered Channel

Can someone explain why, if the channel is buffered, the program does not exit with fatal_error?

Unbuffered channel

package main func main() { c := make(chan int) c <- 3 } fatal error: all goroutines are asleep - deadlock! 

Buffered channel

 package main func main() { c := make(chan int, 1) c <- 3 } [no output] Program exited. 

Thanks!

+8
go
source share
3 answers

Writing to the buffer channel is not blocked if there is space in the buffer.

If you try to put two elements in a channel with a buffer size of one, you will get the same error:

 package main func main() { c := make(chan int, 1) c <- 3 c <- 4 } 

gives you:

 fatal error: all goroutines are asleep - deadlock! 
+11
source share

This is the basic concept of the Go channels (or other CSPs , such as Clojure core.async ) that they block. In general, as you already mentioned, there are two types of channels:

  • buffered, which blocks if the buffer is full.
  • unbuffered block, if not rendezvous, i.e. there must be someone who puts ( c <- ), and someone who takes ( <- c ) from the channel.

In your particular case, the Go runtime is smart enough to detect that none of those who ever take 3 from channel c . Therefore, it is deadlock and (fortunately) an error is thrown.

What you usually do when working with channels is goroutines (checkout is an introduction ), which spawns a light thread controlled by Go runtime - simultaneously executing the body:

 c := make(chan int) go func() { c <- 3 }() // Create a new gorountine that puts 3 to the channel fmt.Println(<- c) // Take 3 from the channel and print it in the main thread 
+2
source share

Thanks @Matt

I found the answer in this post How does make (chan bool) behave differently than make (chan bool, 1)? :

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

+1
source share

All Articles