go程序执行顺序(转)

Wesley13
• 阅读 820

在一个 go 程序中通常包含:包、常量、变量、init()、main()等元素,如果同时存在多个包,包之间存在依赖关系,每个包中存在多个 init 函数,每个文件中存在多个 init 函数,那么问题来了,他们之间的执行顺序是什么样的?通过本文我们来对它们之间的执行顺序做尽可能详尽的说明。如有不正之处,欢迎批评指正。

包的执行顺序

  • 在 main 包中的 go 文件默认总是会被执行
  • 同包下的不同 go 文件,按照文件名“从小到大”排序顺序执行
  • 其他的包只有被 main 包 import 才会执行,按照 import 的先后顺序执行
  • 被递归 import 的包的初始化顺序与 import 顺序相反,例如:导入顺序 main –> A –> B –> C,则初始化顺序为 C –> B –> A –> main
  • 一个包被其它多个包 import,但只能被初始化一次
  • main 包总是被最后一个初始化,因为它总是依赖别的包
  • 避免出现循环 import,例如:A –> B –> C –> A

go 程序的初始化顺序见下图: 
go程序执行顺序(转)

init 和 main 函数

init()、main() 是 go 语言中的保留函数,两个函数在 go 语言中的区别如下: 
相同点:

  • 两个函数在定义时不能有任何的参数和返回值
  • 该函数只能由 go 程序自动调用,不可以被引用

不同点:

  • init 可以应用于任意包中,且可以重复定义多个。
  • main 函数只能用于 main 包中,且只能定义一个。

两个函数的执行顺序:

  • 对同一个 go 文件的 init( ) 调用顺序是从上到下的
  • 对同一个 package 中的不同文件,将文件名按字符串进行“从小到大”排序,之后顺序调用各文件中的init()函数
  • 对于不同的 package,如果不相互依赖的话,按照 main 包中 import 的顺序调用其包中的 init() 函数
  • 如果 package 存在依赖,调用顺序为最后被依赖的最先被初始化,例如:导入顺序 main –> A –> B –> C,则初始化顺序为 C –> B –> A –> main,一次执行对应的 init 方法。

常量、变量、init()、main()

在同一个文件中,常量、变量、init()、main() 依次进行初始化。

init 顺序

1、在同一个 package 中,可以多个文件中定义 init 方法

2、在同一个 go 文件中,可以重复定义 init 方法

3、在同一个 package 中,不同文件中的 init 方法的执行按照文件名先后执行各个文件中的 init 方法

4、在同一个文件中的多个 init 方法,按照在代码中编写的顺序依次执行不同的 init 方法

5、对于不同的 package,如果不相互依赖的话,按照 main 包中 import 的顺序调用其包中的 init() 函数

6、如果 package 存在依赖,调用顺序为最后被依赖的最先被初始化,例如:导入顺序 main –> A –> B –> C,则初始化顺序为 C –> B –> A –> main,一次执行对应的 init 方法。

所有 init 函数都在同⼀个 goroutine 内执⾏。 
所有 init 函数结束后才会执⾏ main.main 函数。

转载

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
科工人 科工人
3年前
go的三个运行基本命令的区别,go run ,go build 和 go install
最近在自学go,遇到点基础的问题,通过自己实际操作之后得出结论在实际操作之前,我们需要知道go有三种源码文件:   1,命令源码文件;声明自己属于main包,并且包含main函数的文件,每个项目只能有一个这样的文件,即程序的入口文件   2,库源码文件;不能直接被执行的源码文件   3,测试源码文件本次操作不涉及测试源码文件。gorun
Wesley13 Wesley13
2年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
2年前
Go 包的原理和使用
Go包的原理和使用包的引出在实际的开发中,我们往往需要在不同的文件中,去调用其它文件的定义的函数,比如main.go中,去使用utils.go文件中的函数,如何实现?包现在有两个程序员共同开发一个Go项目。程序员xiaoming希望定义函数Cal
Stella981 Stella981
2年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Stella981 Stella981
2年前
Python进程、线程、协程的对比
1\.执行过程每个线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在进程中,由进程提供多个线程执行控制。每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。协程,又称微线程,Coroutine。执行过程中,在子程序内部可中断,然后转而
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这