【第十九篇】GO init函数🔥🔥

436 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

一、init 函数:

一、基本介绍:

每一个源文件都可以包含一个init函数,该函数会在main函数执行钱,被GO运行框架调用,也就是说init会在main函数前被调用。

init 函数:函数名必须是init

作用:main 函数之前会先处理这里的内容

init()函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高。init 函数通常被用来:

  • 对变量进行初始化
  • 检查/修复程序的状态
  • 注册
  • 运行一次计算

二、案例说明:

package main

import "fmt"

// init()函数,通常可以在init函数中完成初始化工作
func init() {
	fmt.Println("init()....")
}
func main() {
	fmt.Println("main()....")
}

三、细节讨论:

  1. 如果一个文件同时包含全局变量定义,init 函数 和 main 函数,则执行的流程是:全局变量定义 ---> init 函数 ---> main 函数
  2. init 函数最主要的作用,就是完成一些初始化的工作,比如说下面的案例:
  • 案例一:
package main

import "fmt"

var age = test()

// 为了看到全局变量是先被初始化的,我们这里先写函数

func test() int {
	fmt.Println("test()") // 1
	return 90
}

// init()函数,通常可以在init函数中完成初始化工作
func init() {
	fmt.Println("init()....") // 2
}
func main() {
	fmt.Println("main()....age=", age) // 3
}

  • 案例二:

为了使用导入的包,首先必须将其初始化。初始化总是以单线程执行,并且按照包的依赖关系顺序执行。这通过Golang的运行时系统控制,如下图所示:

  • 初始化导入的包(递归导入)
  • 对包块中声明的变量进行计算和分配初始值
  • 执行包中的init函数

package utils

var Age int
var Name string

// Age 和 Name 全局变量,我们需要在main.go 使用
// 但是我们需要初始化Age 和 Name

// init 函数完成初始化工作

func init() {
	Age = 100
	Name = "tom~"
}
package main

import (
	"fmt"
	// 引入包
	"Program_KF/Goland_Code/chapter_06/func_init_demo_01/utils"
)

var age = test()

// 为了看到全局变量是先被初始化的,我们这里先写函数

func test() int {
	fmt.Println("test()") // 1
	return 90
}

// init()函数,通常可以在init函数中完成初始化工作
func init() {
	fmt.Println("init()....") // 2
}
func main() {
	fmt.Println("main()....age=", age) // 3
	fmt.Println("Age=", utils.Age, "Name=", utils.Name)
}
utils A:  3
utils  init....
utils init2....
main init3....
main全局变量初始化:3
main init.....
main init2....
main  main.....
utils  print....

当我们导入其他包时,会先初始化导入的包,而初始化包时,会先加载全局变量,而后从上到下加载init()函数,当被导入的包的init()函数执行完毕后,执行调用方的全局变量加载,init()函数的顺序加载,之后执行main()函数。

Go包导入规则的副作用

Go要求非常严格,不允许引用不使用的包。但是有时你引用包只是为了调用init函数去做一些初始化工作。此时空标识符(也就是下划线)的作用就是为了解决这个问题。