Go

What does this print? Explain Go's package initialization order.

Question 435HardGo 1.22 to 1.25
package main

import "fmt"

var a = b + 1
var b = f()

func f() int { fmt.Println("f"); return 1 }

func init() { fmt.Println("init1", a, b) }
func init() { fmt.Println("init2") }

func main() { fmt.Println("main") }

Output:

f
init1 2 1
init2
main

The rules:

  1. Imported packages are initialized first, depth-first, and each package exactly once, however many packages import it. Since Go 1.21 the order among independent imports is defined: packages are sorted by import path, and a package is initialized once all its dependencies are.
  2. Inside a package, package-level variables are initialized in dependency order, not source order. a depends on b, so b = f() runs first even though it is declared later. Variables with no dependencies are initialized in declaration order, across files in the order they are given to the compiler (sorted by filename).
  3. Then every init() runs in source order. A package can have many of them, even several in one file, and they cannot be called or referenced.
  4. Finally main.main runs. All of initialization runs in a single goroutine.

Gotchas: an initialization cycle (var x = y; var y = x) is a compile error. Heavy init() work such as network calls, flag parsing or panics hurts testability and startup time. Blank imports (_ "image/png", database drivers) exist only to trigger init registration.

More on Modules, Packages & Tooling

All 36 Modules, Packages & Tooling questions