comparation about keyword "go" and without in Goroutine

Issue

The following code logged an error:

fatal error: all goroutines are asleep – deadlock!

package main

import "fmt"

func main() {
    ch := make(chan int)
    ch <- 1
    fmt.Println(<-ch)
}

But when I changed the code into this:

package main

import "fmt"

func assign (ch chan int) {
    ch <- 1
}

func main() {
    ch := make(chan int)
    go assign (ch)

    fmt.Println(<-ch)
}

“1” was printed out.

Then I used buffered channels:

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

“1” and “2” can also be printed out.

I’m a little confused about the situation. Thanks in advance!

Solution

When you are using unbuffered channel, goroutine is blocked during write until someone does the read.
In your first snippet, there is an unbuffered channel and single goroutine (main goroutine).
So when you are trying to write:

ch <- 1

Nobody reads from the channel yet. The main goroutine is blocked and this line is never executed:

fmt.Println(<-ch)

That’s why you’ve got the deadlock error.

In the second example, you still using unbuffered channel, which means write operation blocks the goroutine.
But by using go you are running the second goroutine.
It means even if this new goroutine will be blocked during write (in your assign function), the main goroutine will continue to work and fmt.Println(<-ch) will be executed and do the read (which in turn unblock background goroutine and assign function will finally reach the end).

To get more understanding about channels and goroutines, this snippet will give the same result (as your second snippet):

package main

import "fmt"

func print(ch chan int) {
    fmt.Println(<-ch)
}

func main() {
    ch := make(chan int)
    go print(ch)
    ch <- 1
}

When you are working with a buffered channel (third snippet), you can do N write operations without blocking goroutine (where N is the size of the buffer).
That’s why in your example you did 2 writes without blocking and is able to read them later. But if your buffer is less than the count of write operations, and nobody do the read, you will fall into the same blocking issues (see the explanation of 1&2 snippets).

Answered By – Ruslan Isay

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.