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
- 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
- init function has no input parameters and return values
- Each package can have multiple init functions
- Each source file of the package can also have multiple init functions
- The execution order of multiple init functions in a source file, the same package and different packages is described in detail below
- 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
- init() calls to the same go file are in top-down order.
- 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.
- 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.
- 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:
- 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)
- 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)
- Execute the init function of the package
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 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.
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:
- init function is executed before main function.
- 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:
-
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:
- 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:
-
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.
-
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:
- 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:
- 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