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.

  1. Initialize the imported package;
  2. Initialize variables in the package scope;
  3. 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…

Thanks for reading, welcome to comment, share, correct ~