Source:Mp.weixin.qq.com/s/HptVvXho3…
Welcome to the public account “Go Back-end Dry Goods”
All kinds of Go, back-end technology, interview questions to share
The body of the
We know that the entry to the Go program is main, and when main exits, the program exits. The init function also plays an important role in Go programs. This article will introduce the features of init functions and how to use them.
The init function does:
- Variable initialization
- Check and fix program status
- Pre-run registrations, e.g. decoder, Parser registrations
- Run modules that only need to be evaluated once, such as sync.once
- other
Package the initialization
If you need to use an imported package, you need to initialize the package first. This step is done by the Runtime before executing the main function.
- Initialize the imported package;
- Initialize variables in the package scope;
- Execute the init function in the package.
If a package is imported more than once, the package initialization is performed only once.
Initialization sequence
A package can contain many files. What is the order in which variables are initialized versus the order in which each package’s init function is executed?
This depends on the order in which files are rendered to the compiler. This is usually in lexicographic order of file names, but dependencies between variables or between packages need to be discussed separately. If z.geo is passed to the build system first, the variable initialization of z.geo is completed before that of A.geo.
In the same package, variables are initialized in lexicographical order by filename, but the Runtime also resolves dependencies between variables. Variables that have no dependencies are initialized first, and init functions are executed in the same order.
Consider the following example of lexicographical initialization by filename:
sandbox.go
package main
import "fmt"
var _ int64 = s()
func init(a) {
fmt.Println("init in sandbox.go")}func s(a) int64 {
fmt.Println("calling s() in sandbox.go")
return 1
}
func main(a) {
fmt.Println("main")}Copy the code
a.go
package main
import "fmt"
var _ int64 = a()
func init(a) {
fmt.Println("init in a.go")}func a(a) int64 {
fmt.Println("calling a() in a.go")
return 2
}
Copy the code
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")
return3}Copy the code
Program output:
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
Copy the code
The following example determines the initialization order by dependency.
pack.go
package pack
import (
"fmt"
"test_util" // Introduce the test_util package
)
var Pack int = 6
func init(a) {
a := test_util.Util
fmt.Println("init pack ", a)
}
Copy the code
test_util.go
package test_util
import "fmt"
var Util int = 5
func init(a) {
fmt.Println("init test_util")}Copy the code
main.go
package main
import (
"fmt"
"pack"
"test_util"
)
func main(a) {
fmt.Println(pack.Pack)
fmt.Println(test_util.Util)
}
Copy the code
Output:
init test_util
init pack 5
6
5
Copy the code
Since the initialization of pack depends on test_util, the runtime initializes the pack package before test_util;
The nature of the init function
The init function takes no arguments and returns no value, and it cannot be called by other functions.
package main
import "fmt"
func init(a) {
fmt.Println("init")}func main(a) {
init()
}
Copy the code
Error: undefined: init
You can also have multiple init functions in a file, as shown in the following code.
sandbox.go
package main
import "fmt"
func init(a) {
fmt.Println("init 1")}func init(a) {
fmt.Println("init 2")}func main(a) {
fmt.Println("main")}Copy the code
utils.go
package main
import "fmt"
func init(a) {
fmt.Println("init 3")}Copy the code
Output: init 1 init 2 init 3 mainCopy the code
The init function is also widely used in standard libraries, such as Math, bzip2, and image.
The most common is to initialize a variable that cannot be initialized with an initializer expression, that is, a variable that cannot be initialized at variable declaration time, as shown in the following example.
var square [10]int
func init(a) {
for i := 0; i < 10; i++ {
square[i] = i * i
}
}
Copy the code
The package is imported simply to execute the init function
It is common in open source code to see packages imported with an underscore “_” in front of them, indicating that they simply want to execute the init function in the package.
import _ "image/png"
Copy the code
The init function in the image/ PNG package registers the image decoder with the image package. See SRC /image/ PNG /reader.go
func init(a) {
image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
}
Copy the code
conclusion
Be careful and do not abuse the init function, because the order in which it is executed can be tricky for more complex projects.
reference
1. Init Functions in Go medium.com/golangspec/…
2. The init function of five minutes to understand golang zhuanlan.zhihu.com/p/34211611
3. When is the Init () Function Run? Stackoverflow.com/questions/2…