I\'ve tried to find a precise explanation of what the init()
function does in Go. I read what Effective Go says but I was unsure if I understood fully what it s
See this picture. :)
import --> const --> var --> init()
If a package imports other packages, the imported packages are initialized first.
Current package's constant initialized then.
Current package's variables are initialized then.
Finally, init()
function of current package is called.
A package can have multiple init functions (either in a single file or distributed across multiple files) and they are called in the order in which they are presented to the compiler.
A package will be initialised only once even if it is imported from multiple packages.
A few more tips:
- There can only be 1 main() function, but there can be many init() functions.
- You do not need to explicitly call init() or main(), they are called automatically.
- init() and main() do not accept any parameters and also don't return anything.
- init() runs before main().
- If you have many init(), they run in the order they are declared.
When is the
init()
function run?
With Go 1.16 (Q1 2021), you will see precisely when it runs, and for how long.
See commit 7c58ef7 from CL (Change List) 254659, fixing issue 41378 .
Runtime: implement
GODEBUG=inittrace=1
supportSetting
inittrace=1
causes the runtime to emit a single line to standard error for each package with init work, summarizing the execution time and memory allocation.The emitted debug information for
init
functions can be used to find bottlenecks or regressions in Go startup performance.Packages with no
init
function work (user defined or compiler generated) are omitted.Tracing plugin inits is not supported as they can execute concurrently. This would make the implementation of tracing more complex while adding support for a very rare use case. Plugin inits can be traced separately by testing a main package importing the plugins package imports explicitly.
$ GODEBUG=inittrace=1 go test init internal/bytealg @0.008 ms, 0 ms clock, 0 bytes, 0 allocs init runtime @0.059 ms, 0.026 ms clock, 0 bytes, 0 allocs init math @0.19 ms, 0.001 ms clock, 0 bytes, 0 allocs init errors @0.22 ms, 0.004 ms clock, 0 bytes, 0 allocs init strconv @0.24 ms, 0.002 ms clock, 32 bytes, 2 allocs init sync @0.28 ms, 0.003 ms clock, 16 bytes, 1 allocs init unicode @0.44 ms, 0.11 ms clock, 23328 bytes, 24 allocs ...
Inspired by stapelberg@google.com who instrumented
doInit
in a prototype to measureinit
times with GDB.
init
will be called everywhere uses its package(no matter blank import or import), but only one time.
this is a package:
package demo
import (
"some/logs"
)
var count int
func init() {
logs.Debug(count)
}
// Do do
func Do() {
logs.Debug("dd")
}
any package(main package or any test package) import it as blank :
_ "printfcoder.com/we/models/demo"
or import it using it func:
"printfcoder.com/we/models/demo"
func someFunc(){
demo.Do()
}
the init will log 0
only one time.
the first package using it, its init func will run before the package's init. So:
A calls B, B calls C, all of them have init func, the C's init will be run first before B's, B's before A's.
https://golang.org/ref/mem#tmp_4
Program initialization runs in a single goroutine, but that goroutine may create other goroutines, which run concurrently.
If a package p imports package q, the completion of q's init functions happens before the start of any of p's.
The start of the function main.main happens after all init functions have finished.