When does the init() function run in GO? [SOLVED]

When does the init() function run in GO? [SOLVED]

Understanding the init() function in GO

Each Go package can optionally havea private function namedinit()that is automatically executed at the beginning of execution time—init()runs when the package is initialized at the beginning of program execution. Theinit()function hasthe following characteristics:

  • init()takes no arguments.
  • init()returns no values.
  • Theinit()function is optional.
  • Theinit()function is called implicitly by Go.
  • You can have aninit()function in themainpackage. In that case,init()is executedbeforethemain()function. In fact, allinit()functions are always executed prior to themain()function.
  • A source file can contain multipleinit()functions—these are executed in the order of declaration.
  • Theinit()function or functions of a package are executed only once, even ifthe package is imported multiple times.
  • Go packages can contain multiple files. Each source file can contain one or moreinit()functions.

The fact that theinit()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 theinit()function, you should think carefully before using aninit()function in public packages or changing any global state ininit().


When should we use init() function?

There are some exceptions where the use ofinit()makes sense:

  • For initializingnetwork 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 illustrateshow Go code is executed. As an example, if amainpackageimports packageAand packageAdepends on packageB, then the following will take place:

  • The process starts withmainpackage.
  • Themainpackage imports packageA.
  • PackageAimports packageB.
  • The global variables, if any, in packageBare initialized.
  • Theinit()function or functions of packageB, if they exist, run. This is the firstinit()function that gets executed.
  • The global variables, if any, in packageAare initialized.
  • Theinit()function or functions of packageA, if there are any, run.
  • The global variables in themainpackage are initialized.
  • Theinit()function or functions ofmainpackage, if they exist, run.
  • Themain()function of themainpackage begins execution.

The following diagramshows what is happening behind the scenes regarding the order of execution of Go code:

image


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 the init()
  • The init() will be invoked before main().
  • Remember that whether or not there is a main function, init() is always called, and if you import a package with an init() 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

Tuan Nguyen

Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise spanning these technologies, he develops robust solutions and implements efficient data processing and management strategies across various projects and platforms.