Deadlock issue when using routine with channel

Issue

I have issue when using Go routine with channel. The code looks like this:

func main() {
    c := make(chan int)
    var wg sync.WaitGroup

    wg.Add(1)
    go func (c chan int, x int) {
        c <- x
        fmt.Println(x)
        close(c)

        defer wg.Done()
    }(c,10)

    wg.Wait()
}

When run the code I got this error:

fatal error: all goroutines are asleep - deadlock!

I cannot understand why this issue happens. Please help me to understand

Solution

You have 2 goroutines in your example: the main goroutine running the main() function, and the other you launch inside it. The main goroutine waits for the other to complete (to call wg.Done()), and the other goroutine blocks in the line where it attempts to send a value on channel c. Since nobody is receiving from that channel, and because that channel is unbuffered, this goroutine will never advance, so all your 2 goroutines will block forever.

Note that defer wg.Done() should be the first statement in the goroutine. If it’s the last, defer won’t make any difference.

If the channel would have a buffer of at least one, the send operation could proceed:

c := make(chan int, 1)

And output will be (try it on the Go Playground):

10

If we leave the channel unbuffered, there must be another goroutine that receives from the channel, e.g.:

wg.Add(1)
go func() {
    defer wg.Done()
    x := <-c
    fmt.Println("Received:", x)
}()

Then output will be (try it on the Go Playground):

10
Received: 10

Answered By – icza

Answer Checked By – Jay B. (GoLangFix Admin)

Leave a Reply

Your email address will not be published.