Go

How does initialization work across packages, and what are the rules for init()?

Question 21MediumGo 1.22 to 1.25

Order of initialization:

  1. Imported packages are initialized first, depth-first. Each package is initialized exactly once, no matter how many packages import it.
  2. Inside a package, all package-level variables are initialized in dependency order.
  3. Then every init() function runs, file by file, in the order they appear.
  4. Finally, main.main runs.

Since Go 1.21, the order among packages that could run at the same point is fully defined: they are sorted by import path.

init rules:

  • It takes no arguments and returns nothing.
  • One package, or even one file, can have many init functions.
  • It can't be called or referenced (init() in your code gives "undefined: init").
  • Everything runs in one goroutine, but init can start goroutines.
import (
	"database/sql"        // used elsewhere: sql.Open("postgres", dsn)
	_ "github.com/lib/pq" // blank import: only runs pq's init(), which calls sql.Register
	_ "net/http/pprof"    // registers /debug/pprof handlers on DefaultServeMux
)

What the interviewer wants to hear: init is fine for registration. It should not be used for I/O, config parsing or anything that can fail. Hidden global state makes testing harder and slows startup. Prefer explicit constructors. Also, flag.Parse() belongs in main, not in init. Since Go 1.13, test flags are registered only when tests start, so parsing in init breaks go test.

More on Language Fundamentals & Types

All 39 Language Fundamentals & Types questions