Go package, Init function and execution sequence

Posted by alexander.s on Sun, 31 Oct 2021 11:36:19 +0100

1, Package concept

  1. The package of Go language is organized in the form of directory tree. Generally, the name of the package is the name of the directory where its source file is located. This is like generating a subdirectory in an existing package. When writing code, all you need to do to import the package is to provide the relative path of the package to be nested.
  2. Go languages are organized as packages, similar to libraries and modules in other languages.
    The hierarchy in the code, circled is the package name, under which multiple source files can be placed (Note: IDE here is VSCODE)

  1. When importing a package with the import syntax followed by the package name, you will first search the GOROOT/src directory to find the package directory. If it is not found, you will go to GOPATH/src
    Keep looking in the directory.
package main//The package name is generally consistent with the directory name of the source file

import ( 	//Import keywords for packages
	"fmt"	//go language internal package, which exists under goroot/src
	"go Test procedure/test01" //Custom package exists in gopath/src
)

fmt package under GOROOT

test01 package under GOPATH

  1. In Go language, if the name of a variable or function starts with an uppercase letter, it is exportable. All other variables or functions whose names do not start with an uppercase letter are private to the package.
  2. The initialization order of recursively imported packages is opposite to the import order. For example, if the import order is main – > a – > b – > C, the initialization order is
    C –> B –> A –> main
  3. A package is import ed by multiple other packages, but can only be initialized once
  4. The main package is always initialized last because it always depends on other packages
  5. If a program is part of the main package, a binary file will be generated during go install, and the main function will be called during execution. If a program is part of a package other than the main package, the package archive file is created when you use the go install command. (run main function = install + execute main)
  6. When a package only needs initialization and does not need to be used, add "" before the package name.

2, Init function

  1. Like the main function, the init function is called by Go when the package is initialized. It does not require any parameters and does not return any values. Init function by Go
    It's called implicitly, so you can't reference it anywhere, but you can call it this way using func init().
  2. **The init function is mainly used to initialize global variables that cannot be initialized in the global code. For example, initialization of arrays.

3, Code execution sequence

The code execution order of Go language is

  1. Initialize all imported packages
  2. Initialize all global variables of the imported package
  3. init function call of imported package
  4. Main function execution
  5. The init function call sequence is

The init() call sequence of the same go file is from top to bottom.

  1. 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.
  2. For different packages, init() in the main package is called in the order of "import first, call first"

An example
main\hello.go

package main //The package name is generally consistent with the directory name of the source file

import ( //Import keywords for packages
	"fmt"           //go language internal package, which exists under goroot/src
	"go Test procedure/test01" //Custom package. The current path is gopath/src
	"go Test procedure/test02"
)

func init() {
	fmt.Println("init=======>main")
}

var testArg = test02.TestArg

func main() {
	fmt.Println("hello world!")
	fmt.Println("getValue", testArg)
	fmt.Println(test01.WriteHelloWorld())
	fmt.Println(test02.WriteHelloWorld())
}

test01\aaatest1.go

package test01

import (
	"fmt"
)

var testArg01 = getArg()

func init() {
	fmt.Println("init=======>aaatest1")
}

func getArg() string {
	fmt.Println("globle init=======>aaatest1")
	return "globle init=======>aaatest1"
}

test01\test01.go

package test01

import (
	"fmt"
)

var testArg = "getTest01Arg"

func init() {
	fmt.Println("init=======>test01 [1]")
}
func init() {
	fmt.Println("init=======>test01 [2]")
}

//WriteHelloWorld test.
func WriteHelloWorld() string {
	return "hello world from test01"
}

test02\test02.go

package test02

import (
	"fmt"
)

var testArg = GetTestArg() //Cannot be accessed by external package
//TestArg globlearg.
var TestArg = GetTestArg()

func init() {
	fmt.Println("init=======>test02")
}

//GetTestArg test.
func GetTestArg() string {
	fmt.Println("Globle Init from test02")
	return "TestArgFromTest02"
}

//WriteHelloWorld test.
func WriteHelloWorld() string {
	return "hello world from test02"
}

Interpretation of operation results:

  1. Start from main. First, find the fmt package under GOROOT/src and import it
  2. Find the test01 package under GOPATH/src / and import it
  3. Because the aaatest1 file name dictionary is before test01, initialize the global variables in aaatest1 and output "globle init =================> aaatest1"
  4. Execute the init function in aaatest1.go and output "init ========= > aaatest1"
  5. Execute init function of test01 in sequence and output
    "init=======>test01 [1]"
    "init=======>test01 [2]"
  6. Find the test02 package under GOPATH/src / and import it
  7. Initialize the two global variables of test02.go and output "global init from TEST02" twice
  8. Execute the init function in test02.go, and output "init =============== > TEST02"
  9. init main package, output "init ========= > main"
  10. Execute the main function in sequence to get the result

4, VSCode compiled pit

1. If you encounter a prompt message such as "exportedxxx should have comment or be unexortedgo lint" (which does not affect program operation), you need to add comments to variables or functions. The comment rule is "variable name (function name) + comment + period", that is

//WriteHelloWorld test.
func WriteHelloWorld() string {
	return "hello world from test01"
}

2. If it is found that vscode automatically deletes the code of the added package after adding the package name in import, you need to check whether the path of the package is correct. If not, vscode will automatically delete the package reference.

Topics: Go Back-end