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函数
init 函数
go语言中 init函数用于包 (package)的初始化,该函数是go语言的一个重要特性。
- init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等(变量常量等声明和数据库 redis 中间件等连接)
- 每个包可以拥有多个init函数
- 同一个包中多个init函数的执行顺序go语言没有明确的定义(实际上是按照顺序执行的)
- 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
- init函数不能被其他函数调用,而是在main函数执行之前,自动被调用
init 函数是初始化包使用,无返回值,无参数,建议每个包只定义一个。init 函数在 import
可以看到main里面什么都没有,但是却打印了init函数里面的语句。
程序执行的时候加载main包,main里面再去加载其他的,在main里面从上到下加载程序,先去加载程序,在加载程序的时候发现import了,这个时候要去找import包并且进行加载。
在找到包进行加载的时候也会从上到下依次进行加载,如果包里面有import那么还会去加载其他的。因为一个包下面有很多go文件,所以在加载的时候会把这些文件都加载进来。加载完之后会看一下有哪些init函数,然后执行所有的init函数,执行完所有init那么第一个import导入工作就算完成了。
import完之后就会执行main函数的加载,如果main包中还有init函数那么也先执行init函数初始化,执行完之后才会执行main函数。(一个包里面可以包含多个init函数)
如果有在一个包下面有多个go文件,里面都有init这个函数,那么执行顺序是随机的。