Go语言中的init函数的执行时机

news/2024/10/22 16:30:45/

init函数的执行时机

  • 这个涉及到
    • init 函数的作用和执行顺序
    • 相同个文件和不同文件中以及在不同的包中init的执行顺序
    • go文件初始化的顺序

一、init 函数的作用和执行顺序

作用

  • init 函数是用于程序执行前做包的初始化的函数,比如初始化包里面的一些变量等等
  • 通常在项目工程中,用来做 Http Server的初始化,DB的初始化, redis 初始化等等中间件的初始化

执行顺序

  • 在同一个 Go 文件可以重复定义多个 init 方法, 它的执行顺序是按照代码编写的顺序依次执行
  • 在同一个 package 里面,不同文件中的 init 方法的执行是按照文件名的顺序先后执行各个文件当中的init方法的
  • 对于不同的package
    • 如果不相互依赖的话,就会按照main包里面 import 的顺序,调用各个包中的init函数
    • 存在依赖,调用顺序就变成最后被依赖的会最先被初始化
      • 比如我们的导入顺序是在main函数中依赖a模块
      • a模块又依赖b模块,b模块又依赖c模块
      • 初始化的顺序就会先初始化c这个包再初始化b这个包再初始化a这个包
      • 最后执行main方法

测试 同一个 Go 文件可以重复定义多个 init 方法

main.go

package mainimport (. "fmt"
)// 同一个go文件中的多个init方法,按照定义的顺序执行
func init() {Println(1)
}func init() {Println(2)
}func main() {}
  • 运行 $ go run main.go
  • 输出
    1
    2
    
  • 可见,按照 定义顺序保持一致

二、相同个文件和不同文件中以及在不同的包中init的执行顺序


2.1 测试同一个包中,不同的文件中的init执行顺序

  • init-demo/
    • go.mod
    • main.go
    • pkg/
      • a.go
      • b.go
      • pkg.go

pkg/a.go

package pkg
import . "fmt"func init() {Println("pkg-a")
}

pkg/b.go

package pkg
import . "fmt"func init() {Println("pkg-b")
}

pkg/pkg.go

package pkg
import . "fmt"var Pkg = "pkg"func init() {Println("pkg-pkg")
}

main.go

package mainimport (. "fmt""init-demo/pkg"
)// 同一个go文件中的多个init方法,按照定义的顺序执行
func init() {Println(1)
}func init() {Println(2)
}func main() {println(pkg.Pkg)
}
  • 执行 $ go run main.go
  • 输出
    pkg-a
    pkg-b
    pkg-pkg
    1
    2
    pkg
    
  • main包依赖pkg包,先按照pkg中包名的 ascII 码的顺序依次执行init, 再执行 main包中的任务
  • 我们知道,先执行 pkg/a.go 中的init, 再执行 pkg/b.go中的init, 再执行 pkg/pkg.go 中的init,最终执行main方法中的任务

测试 导入不同的包有和没有依赖其他包的情况

  • init-demo/
    • go.mod
    • main.go
    • pkg1/
      • pkg1.go
    • pkg2/
      • pkg2.go

pkg1/pkg.go

package pkg1
import "fmt"var Pkg1 = "pkg1"func init() {fmt.Println("pkg1-pkg1")
}

pkg2/pkg.go

package pkg2
import "fmt"
import "init-demo/pkg3"var Pkg2 = "pkg2"func init() {fmt.Println("pkg2-pkg2")
}

pkg3/pkg.go

package pkg3
import ("fmt"
)func init() {fmt.Println("pkg3-pkg3")
}

main.go

package mainimport (. "fmt""init-demo/pkg1""init-demo/pkg2"
)// 同一个go文件中的多个init方法,按照定义的顺序执行
func init() {Println(1)
}func init() {Println(2)
}func main() {println(pkg1.Pkg1)println(pkg2.Pkg2)
}
  • 执行 $ go run main.go

  • 输出

    pkg1-pkg1
    pkg3-pkg3
    pkg2-pkg2
    1
    2
    pkg1
    pkg2
    
  • 先执行pkg1的init,因为在main中被最先引入,优先按照import的顺序执行,接着是pkg3的init, 接着是pkg2的init

  • 因为 pkg3被pkg2引用,这样pkg3的init优先于pkg2的init执行

  • 最后是main包中的init和main函数的方法

三、go文件初始化的顺序

  • 会先初始化引入的包
  • 再初始化当前包中的常量变量
  • 接着初始化当前包中的init函数
  • 最后执行main函数
  • 注意
    • 一个包被引用多次,这个包的init函数只会执行一次 (按照之前的规则的执行顺序下的第一次)
    • 所有的 init 函数都会在同一个 goroutine 内执行
    • 注意包的循环导入问题,会出现异常: import cycle not allowed
  • 这里不再举例

http://www.ppmy.cn/news/1295620.html

相关文章

UE5.1_UMG序列帧动画制作

UE5.1_UMG序列帧动画制作 UMG序列帧动画制作相对比较简单,不像视频帧需要创建媒体播放器那么复杂,以下简要说明: 1. 事件函数 2. 准备序列帧装入数组 3. 构造调用事件函数 4. 预览 序列帧UMG0105 5. 完成!按需配置即可。

mysql服务多实例运行

1、官网下载mysql安装包 https://downloads.mysql.com/archives/community/ 2、解压安装包 tar -zxvf mysql-8.1.0-linux-glibc2.28-aarch64.tar.xz -C /usr/localmv /usr/local/mysql-8.1.0-linux-glibc2.28-aarch64 /usr/local/mysql 3、创建mysql用户组 groupadd…

HCIA-Datacom题库(自己整理分类的)_11_其他网络协议单选【9道题】

1.DNS协议的主要作用是? 文件传输 远程接入 域名解析 邮件传输 2.下列属于链路状态协议的是? Direct static FTP OSPF 解析: FTP:文件传输协议 OSPF:链路状态路由协议 3.如下图所示的网络主机A通过Telnet登录到路由…

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax快速入门 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图 【大数据进阶第三阶段之Datax学习笔记】使用…

Docker使用扩展

日升时奋斗,日落时自省 目录 1、容器 1.1、容器的生命周期 1.1.1、容器OOM 1.1.2、容器异常退出 1.1.3、容器暂停 1.2、容器命令 1.2.1、创建容器 1.2.2、启动容器 1.2.3、容器日志 1.2.4、容器交互 1.2.5、容器停止 1.2.6、扩展 1.3、综合演示 2、存…

Qt之explicit作用及用法

在 Qt 中,explicit 是一个关键字,用于修饰类构造函数。explicit 的主要作用是防止隐式类型转换,即禁止编译器使用该构造函数进行隐式类型转换。 在 C 中,当一个构造函数只接受一个参数的时候,它可能会被用于执行隐式类…

网络安全与IP地址:构建数字世界的前沿堡垒

网络安全是当今数字社会中不可忽视的挑战之一。而IP地址,作为互联网通信的基础协议,既是数字化时代的桥梁,也是网络安全的关键节点。本文将剖析IP地址在网络安全领域的作用,以及如何利用其特性建立有效的网络安全策略。 IP地址&a…

win10提示“KBDSF.DLL文件缺失”,游戏或软件无法启动运行,快速修复方法

很多用户在日常使用电脑的时候,或多或少都遇到过,在启动游戏或软件的时候,Windows桌面会弹出错误提示框“KBDSF.DLL文件缺失,造成软件无法启动或运行,请尝试重新安装解决”。 首先,先来了解DLL文件是什么&a…