Go

What does the Go memory model guarantee about starting and ending a goroutine?

Question 180HardGo 1.22 to 1.25

Two rules matter:

  • The go statement that starts a goroutine is synchronized before the start of that goroutine. Writes the parent made before go are visible to the child.
  • The exit of a goroutine is not synchronized with anything. Nothing the child writes is guaranteed visible to anyone unless you add synchronization (channel, WaitGroup, mutex, atomics).
var a string

func main() {
	a = "hello"
	go func() { fmt.Println(a) }() // guaranteed to see "hello" (if it runs)

	var b string
	go func() { b = "hi" }()
	fmt.Println(b) // racy: may print an empty string
}

The fix for the second case is to publish through a synchronizing operation. For example, create done := make(chan struct{}), call close(done) in the child after the write, and do <-done in the parent before the read. wg.Wait() gives the same guarantee: every Done is synchronized before the Wait it unblocks.

What the interviewer wants to hear: "it worked when I ran it" proves nothing. Sleeps are not synchronization, and busy-waiting on a plain bool can loop forever because the compiler may keep the value in a register. Use atomic.Bool or a channel.

More on Goroutines & the Scheduler

All 35 Goroutines & the Scheduler questions