[Go] Init function and main function in Go language

1, init function

1. Function of init function

The init function in go language is used for package initialization. This function is an important feature of go language.

The main functions are:

  • Initializes a variable that cannot be initialized with an initialization expression.
  • Registration before running the program.
  • Implement the sync.Once function.
  • other

2. Characteristics of init function

  1. Init function is used to initialize the package before program execution (program execution starts from main function and init is executed before main), such as initializing variables in the package
  2. init function has no input parameters and return values
  3. Each package can have multiple init functions
  4. Each source file of the package can also have multiple init functions
  5. The execution order of multiple init functions in a source file, the same package and different packages is described in detail below
  6. The init function cannot be called by other functions, but is automatically called by the program before the main function is executed

3. Execution sequence of multiple init functions

  1. init() calls to the same go file are in top-down order.
  2. For different files in the same package, the init() function in each file is called in the order of "from small to large" by comparing the file name string.
  3. For different package, if it does not depend on each other, call the init() in its package according to the order of "first call of import" in the main package. If package exists, then the init() in the earliest package is called, and finally the main function is called. In other words, if there are dependencies between packages, init() of packages without dependencies will be called first to the packages with the most dependencies.
  4. If println() or print() is used in the init function, you will find that these two will not be executed in the order you think. These two functions are only recommended to be used in the test environment, but not in the formal environment.

4. Go program initialization

The initialization of the golang program is performed before the main function and is initiated by the runtime. The initialization sequence is as follows:

  1. Initialize the imported package (the initialization order of the package is not "top-down" in the import order. The runtime needs to resolve the package dependency. First initialize the package without dependency, which is similar to variable initialization dependency)
  2. Initialize the variables of the package scope (the initialization of the variables of the scope is not in the order of "from top to bottom and from left to right". The runtime resolves the variable dependencies and initializes the variables without dependencies first)
  3. Execute the init function of the package

2, main function

The default entry function (main function) of Go language program: func main(). After the main function returns, the program ends.

The function body is wrapped with {a pair of parentheses:

func main(){
    //Function body
}

3, Similarities and differences between init function and main function

Similarities:
The two functions cannot have any parameters and return values when they are defined, and the Go program automatically calls them (generally, the functions must be declared first and then called. The init function and main function are only declared, and the Go program will enter by itself).

difference:
init can be applied to any package, and multiple can be defined repeatedly.
The main function can only be used in the main package, and only one can be defined.

4, Instance

Example 1

package main

import (
	"fmt"
)

func main() {
	fmt.Println("do in main")
}

// the other init function in this go source file
func init() {
	fmt.Println("do in init")
}

func testf() {
	fmt.Println("do in testf")
	//if uncomment the next statment, then go build give error message : .\gprog.go:19: undefined: init
	//init()
}

Output results:

do in init
do in main

Example 1 Description:

  1. init function is executed before main function.
  2. Both the init function and the main function are automatically invoked by the program. The program is automatically entered into execution without explicit call. It can not be invoked in other functions, and explicit calls will declare the function undefined.

Example 2

Edit two files:

File 1: the file name is inma.go, and the content is as follows

package main

import (
    "fmt"
)

// the other init function in this go source file
func init() {
    fmt.Println("do in init")
}

func main() {
    fmt.Println("do in main")
}

func testf() {
    fmt.Println("do in testf")
    //if uncomment the next statment, then go build give error message : .\gprog.go:19: undefined: init
    //init()
}

File 2: file name inin.go, as follows

package main

import (
    "fmt"
)

// the first init function in this go source file
func init() {
    fmt.Println("do in init1")
}

// the second init function in this go source file
func init() {
    fmt.Println("do in init2")
}

Compile the above two files: go build inma.go inin.go

After compilation, execute inma.exe and output the following results:

do in init
do in init1
do in init2
do in main

Screenshot of the process: (both files are in the hello package)

Description of example 2:

  1. The init function in inma.go is executed first, then the two init functions in inin.go are executed, and then the main function is executed.

    This means that the main function will not be executed until all init functions in all go source files in a package are executed.

Example 3

package main

import (
	"fmt"
)

var T int64 = a()

func init() {
	fmt.Println("init in main.go ")
}

func a() int64 {
	fmt.Println("calling a()")
	return 2
}
func main() {
	fmt.Println("calling main")
}

Output results:

calling a()
init in main.go 
calling main

Description of example 3:

  1. Initialization sequence: variable initialization - > init() - > main()

Example 4

Create three packages:

There is a source file pack.go in the pack package:

package pack                                                                                                                     

import (
   "fmt"
   "test_util"
)

var Pack int = 6               

func init() {
   a := test_util.Util        
   fmt.Println("init pack ", a)    
} 

test_ There is a source file test in the util package_ util.go :

package test_util                                                                                                                

import "fmt"

var Util int = 5

func init() {
   fmt.Println("init test_util")
}  

There is a source file main.go in the hello package:

package main                                                                                                                     

import (
   "fmt"
   "pack"
   "test_util"                
)

func main() {                  
   fmt.Println(pack.Pack)     
   fmt.Println(test_util.Util)
}

Compile the three packages and execute hello.exe (i.e. main.go):

Output results:

init test_util  //Execute test_ init() function of util package
init pack  5    //Execute the init() function of the pack package
6               //main function of hello package: pack.Pack
5               //main function of hello package: test_util.Util

Description of example 4:

  1. Let's first analyze the package dependency: the package depends on test_util package; test_ The util package does not depend on any package.

    Therefore, when running, initialize test first_ Util package, and then initialize the pack package: that is, execute test first_ Init() function in util, and then execute init() function in pack package.

    In other words, when the program is executed, the packages you import will be initialized. If there are dependencies between these packages, the packages without dependencies will be initialized first (that is, call init()), and so on. Finally, the packages with the most dependencies will be initialized.

  2. Init function is executed before main function. After all init functions are executed, the main function will be executed.

Example 5

Write three source files in the same package:

sandbox.go:

package main

import "fmt"

var _ int64 = s()

func init() {
	fmt.Println("init in sandbox.go")
}
func s() int64 {
	fmt.Println("calling s() in sandbox.go")
	return 1
}
func main() {
	fmt.Println("main")
}

a.go:

package main

import "fmt"

var _ int64 = a()

func init() {
	fmt.Println("init in a.go")
}
func a() int64 {
	fmt.Println("calling a() in a.go")
	return 2
}

z.go:

package main

import "fmt"

var _ int64 = z()

func init() {
	fmt.Println("init in z.go")
}
func z() int64 {
	fmt.Println("calling z() in z.go")
	return 3
}

Output results:

calling a() in a.go
calling s() in sandbox.go
calling z() in z.go
init in a.go
init in sandbox.go
init in z.go
main

Description of example 5:

  1. The execution order of init functions of different source files in the same package is the dictionary order of source file names.

Example 6

package main

import "fmt"

var initArg [20]int

func init() {
	initArg[0] = 10
	for i := 1; i < len(initArg); i++ {
		initArg[i] = initArg[i-1] * 2
	}
}

func main() {
	fmt.Println(initArg)
	fmt.Println("main")
}

Output results:

[10 20 40 80 160 320 640 1280 2560 5120 10240 20480 40960 81920 163840 327680 655360 1310720 2621440 5242880]
main

Example 6 Description:

  1. Main purpose of init function: initialize variables that cannot be initialized with initialization expressions

Example 7

import _ "net/http/pprof"

explain:

The Go language compiles and reports errors for unused import packages, but sometimes we just want to call the init function of the package without using the variables or methods exported by the package. In this case, the above import scheme is adopted.

After executing the above import, the init function will start an asynchronous process to collect the resource usage of the process instance and provide it to the user for query in the form of http service interface.

Reference link

  1. Init function and main function
  2. init function of go language
  3. Five minutes to understand golang's init function

Tags: Go Back-end

Posted on Wed, 01 Dec 2021 16:48:42 -0500 by Domcsore