syntagma
syntagma

Reputation: 24314

Closing channels in Go

I am learning how channels work in Go and have stumbled upon a problem with closing the channels. This is a modified example from A Tour of Go, which generates n-1 fibonacci numbers and sends them through the channels, leaving the last "element" of the channel capacity unused.

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n-1; i++ {
        c <- x
        x, y = y, x+y

    }
    // close(c) // It's commented out on purpose
}

func main() {
    n := 10
    c := make(chan int, n)
    go fibonacci(n, c)

    for i := 0; i < n; i++ {
        _, ok := <-c
        fmt.Println(ok)
    }
}

The problem is that I get:

fatal error: all goroutines are asleep - deadlock!

when I do not close the channel. What exactly is causing the deadlock? Why can't I receive from the channel in its capacity boundaries when I don't close it?

Upvotes: 0

Views: 3005

Answers (2)

helmbert
helmbert

Reputation: 37964

You're writing n values into the channel (from 0 to n-1), but are trying to read n+1 values from the channel (from 0 to n). Without explicitly closing the channel, the main function will wait forever for this last value.

What exactly is causing the deadlock?

After n iterations, the goroutine running the fibonacci function will exit. After this goroutine has exited, the only remaining goroutine in your program is the main goroutine, and this goroutine is waiting for some data to be written to the c channel -- and since there is no other goroutine left that might ever write data into this channel, it will wait forever. This is exactly what the error message is trying to tell you: "all goroutines ("all" is just "one", here) are asleep".

The _, ok := <- c call in the main function will only stop blocking as soon as the c channel is closed (as reading from a channel is blocking, this needs to be done from another goroutine). When the channel is closed, the main function will read remaining data from the channel (when it's a buffered channel)

Upvotes: 5

Uvelichitel
Uvelichitel

Reputation: 8490

For loop in main expect n communication in channel, but you produce only n-1 in func fibonacci

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ { //here
        c <- x
        x, y = y, x+y

    }
    // close(c) // It's commented out on purpose
}

should work http://play.golang.org/p/zdRuy14f9x

Upvotes: 0

Related Questions