Why does the use of an unbuffered channel in the same goroutine result in a deadlock?

From the documentation :

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.

Said otherwise :

  • when a channel is full, the sender waits for another goroutine to make some room by receiving
  • you can see an unbuffered channel as an always full one : there must be another goroutine to take what the sender sends.

This line

c <- 1

blocks because the channel is unbuffered. As there’s no other goroutine to receive the value, the situation can’t resolve, this is a deadlock.

You can make it not blocking by changing the channel creation to

c := make(chan int, 1) 

so that there’s room for one item in the channel before it blocks.

But that’s not what concurrency is about. Normally, you wouldn’t use a channel without other goroutines to handle what you put inside. You could define a receiving goroutine like this :

func main() {
    c := make(chan int)    
    go func() {
        fmt.Println("received:", <-c)
    }()
    c <- 1   
}

Demonstration

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)