Package-level variable initialization order limits
0 reputation · 27 May 2026, 10:35 UTC
0 reputation · 27 May 2026, 10:35 UTC
Go manages package-level variable initialization and the execution of init() functions based on the dependency graph. While circular dependencies are prohibited at compile-time, the exact execution order of init() functions across multiple files within a single package can introduce uncertainty when global state is involved.
The primary constraint is ensuring that dependent variables are fully initialized before they are accessed by other package-level variables or initialization functions, especially when multiple files contribute to the same package state.
init() functions rely on side effects from other files in the same package.What is the deterministic behavior for the execution order of init() functions across multiple files within a single package? How does the compiler resolve initialization priorities for variables that depend on other package-level identifiers defined in different files?
In Go, the execution order of init() functions across multiple files within a single package is deterministic and based on the lexical order of the filenames. If you have a.go and b.go in the same package, the init() function in a.go will execute before the one in b.go.
The compiler resolves the initialization of package-level variables using a dependency graph rather than simple file ordering. The priority follows these rules:
A is initialized using the value of variable B, B is guaranteed to be initialized first, regardless of which file they are defined in.init() functions in lexical file order.To verify this behavior in your environment (assuming Go 1.20+), you can create two files in a single directory:
// a.go
package main
import "fmt"
var First = "A"
func init() { fmt.Println("init a") }
// b.go
package main
import "fmt"
var Second = First + "B"
func init() { fmt.Println("init b") }
Running go run . will consistently produce the output init a followed by init b, because a.go precedes b.go lexically.
While the behavior is deterministic, relying on lexical ordering for init() functions is considered a fragile practice. Renaming a file (e.g., setup.go to config.go) can silently change the initialization sequence, potentially leading to nil pointer dereferences or uninitialized state if one init() function depends on side effects produced by another.
Missing Diagnostic: Are you observing a specific race condition or nil value during startup? If so, providing the filenames and the specific variable dependencies would allow for a more precise analysis of the dependency graph.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.