Search code examples
goconcurrencygoroutinechannel

Why is "Greetings done" getting printed before "Bonjour" in the below example of goroutines and channels?


In the below example, Why is "Greetings done" getting printed before "Bonjour" ? Shouldn't the sender routine wait until receiver routine receives the value in channel ?

package main

import (
    "fmt"
)

func greetings(c chan string) {
    fmt.Println(<-c)
    c <- "Bonjour"
    fmt.Println("Greetings done")
}

func main() {
    myChannel := make(chan string)

    // creates routine and leaves it upto Go to execute
    go greetings(myChannel)

    // while greetings() routine is getting executed, a new value is written to channel by main function
    myChannel <- "hi from main"
    // now main function (sender routine) is blocked. It wont proceed until another routine reads from the channel

    // By then greetings() routine will read the value and prints it. Hence "hi from main" gets printed

    // Now main function proceeds and moves to next line
    // simultaneously, greetings() would have written "Bonjour" to channel

    // main routine will receive it and prints it
    fmt.Println(<-myChannel)
    fmt.Println("main done")
}

The output of the program is:
hi from main
Greetings done
Bonjour
main done

Shouldn't the sender routine wait until receiver routine receives the value in channel ? Meaning Shouldn't "Greetings done" be printed after "Bonjour" ? Because the sender routine (greetings) will be blocked until the main routine receives its value.


Solution

  • "Greetings done" and "Bonjour" have no defined order with respect to each other. In other words, they may appear in either order, and that would still be valid behaviour of the program.

    Shouldn't "Greetings done" be printed after "Bonjour" ? Because the sender routine (greetings) will be blocked until the main routine receives its value.

    It's correct that the sender will be blocked until the main goroutine receives its value. Still, the main goroutine must print the value after receiving it.

        // main routine will receive it and prints it
        fmt.Println(<-myChannel)
    

    This comment is basically correct, but just because it does A and B (receives and prints), doesn't mean A and B happen at the same time. It's only the receiving of the value that is synchronized.