Go init 初始化函数

init可以用在比如后面和数据库相关的时候,将连接初始化一下,同时初始化一些驱动也是这个原理。后面还有很多包使用下划线_来导入的,其实就是执行一下包里面的init函数,并不会去使用包名+方法。 

 

init函数 


 每一个源文件都可以包含一个init函数,该函数会在main函数执行前,被Go运行框架调用,也就是说init会在main函数前被调用。main函数和init函数相同点都是没有入参,而且没有返回值。 

func main() {
	fmt.Println("main")
}

func init() {
	fmt.Println("init")
}

init
main

通常可以在init函数当中完成初始化的工作,init初始化一般用于哪些场景,比如db的包,那么init函数一般是去做数据库连接等。比如导入db等包,里面有初始化函数,这个初始化函数就是用来连接数据库等。

细节讨论:

(1)如果一个文件同时包含全局变量定义,init函数和main函数,则执行的流程是:全局变量定义--->init函数--->main函数,也就是全局变量的定义是最先执行的。

(2)init函数最主要的作用,就是完成一些初始化的工作,比如下面的案例:初始数据库连接。

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var (
	username = "root"
	password = "sMo!G(LbU13E11"
	host     = "192.168.87.128"
	port     = 3306
	dbname   = "test"
	timeout  = "10s"
	DB       *gorm.DB
)

func init() {
	dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s",
		username, password, host, port, dbname, timeout)
	//连接MySQL,获取DB类型实例,用于后面数据库读写操作
	db, err := gorm.Open(mysql.Open(dns), &gorm.Config{})
	if err != nil {
		panic(err)
	}
	DB = db
}

type User struct {
	ID       int64 `gorm:"primary_key"`
	Username string
	Password string
}

func main() {
	//连接成功
	fmt.Println(DB)
}

&{0xc00011a5a0 <nil> 0 0xc00021e000 1}

3)面试题:案例如果main.go和utils.go都含有变量定义,init函数时,执行的流程又是怎么样的呢?

首先执行被引入文件当中的变量定义,然后执行被引入文件的init函数,最后执行main里面。 

init函数和main函数的异同


相同点: 两个函数在定义时不能有任何的参数和返回值,且Go程序自动调用。

不同点:
  • init可以应用于任意包中,且可以重复定义多个。
  • main函数只能用于main包中,且只能定义一个。
两个函数的执行顺序:
  • 对同一个go文件的 init() 调用顺序是从上到下的。
  • 对同一个package中不同文件是按文件名字符串比较从小到大顺序调用各文件中的 init() 数。
  • 对于不同的 package ,如果不相互依赖的话,按照main包中"import 的后调用"的顺序调用 其包中的 init() 如果 package 存在依赖,则先调用最早被依赖的 package 中的 init() ,最后调用 main 函数。

main函数


main 包用于声明告知编译器将包编译为二进制可执行文件 ,在 main 包中的 main 函数是程序的入口,无返回值,无参数。 main函数也常常写在main包里面,在其他地方不写。(在其他包里面是不写main函数的)

init 函数


go语言中 init函数用于包 (package)的初始化,该函数是go语言的一个重要特性。

有下面的特征:
  • init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等(变量常量等声明和数据库 redis 中间件等连接)
  • 每个包可以拥有多个init函数
  • 同一个包中多个init函数的执行顺序go语言没有明确的定义(实际上是按照顺序执行的)
  • 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
  • init函数不能被其他函数调用,而是在main函数执行之前,自动被调用

init 函数是初始化包使用,无返回值,无参数,建议每个包只定义一个。init 函数在 import

包时自动被调用(const->var->init)。
初始化函数就是在导入包的时候执行的

_用来做初始化导入的 

可以看到main里面什么都没有,但是却打印了init函数里面的语句。

程序执行的时候加载main包,main里面再去加载其他的,在main里面从上到下加载程序,先去加载程序,在加载程序的时候发现import了,这个时候要去找import包并且进行加载。

在找到包进行加载的时候也会从上到下依次进行加载,如果包里面有import那么还会去加载其他的。因为一个包下面有很多go文件,所以在加载的时候会把这些文件都加载进来。加载完之后会看一下有哪些init函数,然后执行所有的init函数,执行完所有init那么第一个import导入工作就算完成了。

import完之后就会执行main函数的加载,如果main包中还有init函数那么也先执行init函数初始化,执行完之后才会执行main函数。(一个包里面可以包含多个init函数)

如果有在一个包下面有多个go文件,里面都有init这个函数,那么执行顺序是随机的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值