Why does this part of the code gets executed before the other?

Issue

I am very new to Go and I am trying to learn about unbuffered channels and goroutines.

I have this code:

func main() {

var waitGroup sync.WaitGroup
waitGroup.Add(3)

c := make(chan int)

go func() {
    defer waitGroup.Done()
    x := 1
    res := x * 2
    fmt.Println(x, "* 2 = ", res)
    c <- x

}()

go func() {
    defer waitGroup.Done()
    x := <-c
    res := x * 3
    fmt.Println(x, "* 3 = ", res)
    c <- x
}()

go func() {
    defer waitGroup.Done()
    x := <-c
    res := x * 4
    fmt.Println(x, "* 4 = ", res)
}()

waitGroup.Wait()
close(c)

}

So i expect the output to be:

1 * 2 =  2
1 * 3 =  3
1 * 4 =  4

Instead I get:

1 * 2 =  2
1 * 4 =  4
fatal error: all goroutines are asleep - deadlock!

I really don’t understand why the second func gets executed after the third. How can I get the result without changing the channel to a buffered channel.

Solution

You seem to expect the <- operator to care what order the goroutines were created in. That’s not promised (or even likely). If two <- operators are reading the same channel, which one gets the value is random. If you want to order this, you’d need to create another channel that the second goroutine writes to and the third one reads.

Buffering wouldn’t help here, since the problem isn’t that it blocks on write. It’s that the third function consumes a value and doesn’t generate one, so the second function has nothing to read.

Go Playground

Answered By – Rob Napier

Answer Checked By – Marie Seifert (GoLangFix Admin)

Leave a Reply

Your email address will not be published.