Go

What happens when main returns while other goroutines are still running? What does this print?

Question 166MediumGo 1.22 to 1.25
package main

import "fmt"

func main() {
	go func() {
		defer fmt.Println("deferred")
		fmt.Println("in goroutine")
	}()
	fmt.Println("main done")
}

Most likely it prints only main done. When main.main returns, the runtime calls exit(0) right away. Other goroutines are not waited for, and their deferred calls do not run. Sometimes you will see in goroutine as well, but nothing guarantees it.

The fix is to wait explicitly with sync.WaitGroup, a done channel, or errgroup. Go 1.25 added wg.Go(f), which does Add and Done for you:

var wg sync.WaitGroup
wg.Go(func() { fmt.Println("in goroutine") })
wg.Wait()

Related: os.Exit also skips deferred calls, even in the current goroutine. runtime.Goexit() called in main ends main but lets the other goroutines keep running. If they all finish or block, you get "fatal error: no goroutines (main called runtime.Goexit) - deadlock!".

More on Goroutines & the Scheduler

All 35 Goroutines & the Scheduler questions