Go

Is msg guaranteed to print "hello"? Compare unbuffered and buffered channels.

Question 500HardGo 1.22 to 1.25
var msg string

func main() {
    c := make(chan int)      // unbuffered
    go func() {
        msg = "hello"
        <-c                  // receive
    }()
    c <- 0                   // send
    fmt.Println(msg)
}

Yes, with an unbuffered channel. The Go memory model says: "A receive from an unbuffered channel is synchronized before the completion of the corresponding send on that channel." The goroutine writes msg before its receive, and the receive happens before main's send completes. So the write happens before the print.

If you change it to make(chan int, 1), the guarantee disappears. The send completes right away into the buffer, main may print an empty string, and it is a data race. For a buffered channel with capacity C, the rule is that the k-th receive happens before the (k+C)-th send completes. That is the rule that lets a buffered channel work as a counting semaphore.

The usual direction also holds for all channels: a send happens before the matching receive completes, so msg = "x"; done <- true in the goroutine with <-done in main is always safe. The interviewer wants to know whether you reason with happens-before rather than with timing or time.Sleep.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions