Summary:
Basic rules:
- All init functions are executed in a Goroutine (but see special note below).
- If package a references package b, then a's init function is guaranteed to run after b's init function has completed.
- The main function in the main package is guaranteed to run after all other init functions have completed (i.e., the execution order is package init -> main init -> main main).
- The execution order of init functions in multiple files within the same package is undefined, but within the same file, init functions are executed from top to bottom.
- If package a references both package b and c, the init order of b and c is defined in Go1.21 and later.
In Go1.20 and earlier:
- If package a references package b, then b's init function is guaranteed to run before a's init function.
- However, if package a references both package b and c, and there is no reference relationship between b and c, the execution order of b and c is undefined.
In Go1.21 and later:
- For packages without reference relationships (i.e., the second point in Go1.20 and earlier), the reference order is determined by the alphabetical order of package names (e.g., a is guaranteed to run before b, github.com/xxx/xxx is guaranteed to run before gitlab.com/xxx/xxx).
Special note:
- If there is blocking in an init function, the Goroutine used to run the init function may create new Goroutines, resulting in concurrent execution of some init code.
- In the presence of blocking, there is no guarantee of the completion order of init functions in packages without reference relationships (see example c).
- In the presence of blocking, if package a depends on package b, a's init function is guaranteed to start running after b's init function has completed (see example d).
Example project:
References: