Understanding the init() function in GO
Each Go package can optionally have a private function named init()
 that is automatically executed at the beginning of execution time—init()
 runs when the package is initialized at the beginning of program execution. The init()
 function has the following characteristics:
init()
 takes no arguments.init()
 returns no values.- TheÂ
init()
 function is optional. - TheÂ
init()
 function is called implicitly by Go. - You can have anÂ
init()
 function in the main package. In that case,Âinit()
 is executed before theÂmain()
 function. In fact, allÂinit()
 functions are always executed prior to theÂmain()
 function. - A source file can contain multipleÂ
init()
 functions—these are executed in the order of declaration. - TheÂ
init()
 function or functions of a package are executed only once, even if the package is imported multiple times. - Go packages can contain multiple files. Each source file can contain one or moreÂ
init()
 functions.
The fact that the init()
 function is a private function by design means that it cannot be called from outside the package in which it is contained. Additionally, as the user of a package has no control over the init()
 function, you should think carefully before using an init()
 function in public packages or changing any global state in init()
.
When should we use init() function?
There are some exceptions where the use of init()
 makes sense:
- For initializing network connections that might take time prior to the execution of package functions or methods.
- For initializing connections to one or more servers prior to the execution of package functions or methods.
- For creating required files and directories.
- For checking whether required resources are available or not.
Order of execution
This subsection illustrates how Go code is executed. As an example, if a main
 package imports package A
 and package A
 depends on package B
, then the following will take place:
- The process starts withÂ
main
 package. - The main package imports packageÂ
A
. - PackageÂ
A
 imports packageÂB
. - The global variables, if any, in packageÂ
B
 are initialized. - TheÂ
init()
 function or functions of packageÂB
, if they exist, run. This is the firstÂinit()
 function that gets executed. - The global variables, if any, in packageÂ
A
 are initialized. - TheÂ
init()
 function or functions of packageÂA
, if there are any, run. - The global variables in theÂ
main
 package are initialized. - TheÂ
init()
 function or functions ofÂmain
 package, if they exist, run. - TheÂ
main()
 function of theÂmain
 package begins execution.
The following diagram shows what is happening behind the scenes regarding the order of execution of Go code:
Sample init() function
Here is an example of using the init()
function in Go:
package main
import "fmt"
var intValue = InitInt()
func InitInt() int {
return 2022
}
func init() {
intValue = 10000
}
func main() {
fmt.Println("init value:", intValue)
}
Output:
init value: 10000
Explanation:
- It is assumed that the function
initInt()
will be called before theinit()
- The
init()
will be invoked beforemain()
. - Remember that whether or not there is a main function,
init()
is always called, and if you import a package with aninit()
method, it will be invoked.
Using multiple init() functions
With single package
In this example, we will define many init() functions within a file, and then see the order of functions called:
package main
import (
"fmt"
)
var intValue = InitInt()
func InitInt() int {
fmt.Println("This is global variable initialization!")
return 2022
}
func init() {
fmt.Println("This is the last init call")
}
func init() {
fmt.Println("This is the first init call")
}
func init() {
fmt.Println("This is the second init call")
}
func main() {
fmt.Println("This is main function!")
}
Output:
This is global variable initialization!
This is the last init call
This is the first init call
This is the second init call
This is main function!
We can see that the global variable initialization will be called first, and they init() functions will be executed in the order they show up in the file.
With dependency packages
Each package allows for multiple init()
functions, which will be performed in the order they appear in the file (after all variables are initialized). Â If they span multiple files, they will be executed in lexical file name order. Here is an example of one package have 2 file: hello1.go and abc.go:
hello1.go
package hello
import "fmt"
var hello1 = HelloFunction1()
func init() {
fmt.Println("This is init function from hello1.go")
}
func HelloFunction1() bool {
fmt.Println("Hello1.go file...")
return true
}
abc.go
package hello
import "fmt"
var testVal = InitFromFuncABC()
func init() {
fmt.Println("This is init function from abc.go")
}
func InitFromFuncABC() bool {
fmt.Println("Init from abc.go...")
return true
}
main.go:
package main
import (
"fmt"
_ "hello"
)
func main() {
fmt.Println("From main function")
}
Output:
Init from abc.go...
Hello1.go file...
This is init function from abc.go
This is init function from hello1.go
From main function
You can see that because we import the hello package; the program will first initialize the global variable and init() function from abc.go, and then initialize the global variable and init() function from hello1.go and finally it will run the main function.
Summary
The init()
functions will be called:
- After the package-level variables (global variables, package imports,...).
- If multiple init() functions, they will be called in the order they show up in the file.
- Before the main function (optionally).
The init()
will be called everywhere uses its package (no matter blank import or import), but only one time. If they span multiple files, they will be executed in lexical file name order.
References
https://go.dev/doc/effective_go#init
go - When is the init() function run? - Stack Overflow