go包中的init() 函数
https://tutorialedge.net/golang/the-go-init-function/
-----------------------------------------------------------------------
There are times, when creating applications in Go, that you need to be able to set up some form of state on the initial startup of your program. This could involve creating connections to databases, or loading in configuration from locally stored configuration files.
When it comes to doing this in Go, this is where your init() functions come into play. In this tutorial, we’ll be looking at how you can use this init()function to achieve fame and glory, or more likely to help you to build your next Go based project.
The init Function
In Go, the init() function is incredibly powerful and compared to some other languages, is a lot easier to use within your Go programs. These init()functions can be used within a package block and regardless of how many times that package is imported, the init() function will only be called once.
Now, the fact that it is only called once is something you should pay close attention to. This effectively allows us to set up database connections, or register with various service registries, or perform any number of other tasks that you typically only want to do once.
package main
func init() {
  fmt.Println("This will get called on main initialization")
}
func main() {
  fmt.Println("My Wonderful Go Program")
}Notice in this above example, we’ve not explicitly called the init() function anywhere within our program. Go handles the execution for us implicitly and thus the above program should provide output that looks like this:
$ go run test.go
This will get called on main initialization
My Wonderful Go ProgramAwesome, so with this working, we can start to do cool things such as variable initialization.
package main
import "fmt"
var name string
func init() {
    fmt.Println("This will get called on main initialization")
    name = "Elliot"
}
func main() {
    fmt.Println("My Wonderful Go Program")
    fmt.Printf("Name: %s\n", name)
}In this example, we can start to see why using the init() function would be preferential when compared to having to explicitly call your own setup functions.
When we run the above program, you should see that our name variable has been properly set and whilst it’s not the most useful variable on the planet, we can certainly still use it throughout our Go program.
$ go run test.go
This will get called on main initialization
My Wonderful Go Program
Name: ElliotMultiple Packages
Let’s have a look at a more complex scenario that is closer to what you’d expect in a production Go system. Imagine we had 4 distinct Go packages within our application, main, broker, and database.
In each of these we could specify an init() function which would perform the task of setting up the connection pool to the various 3rd party services such as Kafka or MySQL.
Whenever we then call a function in our database package, it would then use the connection pool that we set up in our init() function.
Note - It’s incredibly important to note that you cannot rely upon the order of execution of your
init()functions. It’s instead better to focus on writing your systems in such a way that the order does not matter.
Order of Initialization
For more complex systems, you may have more than one file making up any given package. Each of these files may indeed have their own init()functions present within them. So how does Go order the initialization of these packages?
When it comes to the order of the initialization, a few things are taken into consideration. Things in Go are typically initialized in the order in declaration order but explicitly after any variables they may depend on. This means that, should you have 2 files a.go and b.go in the same package, if the initialization of anything in a.go depends on things in b.go they will be initialized first.
Note - A more in-depth overview of the order of initialization in Go can be found in the official docs: Package Initialization
The key point to note from this is this order of declaration can lead to scenarios such as this:
// source: https://stackoverflow.com/questions/24790175/when-is-the-init-function-run
var WhatIsThe = AnswerToLife()
func AnswerToLife() int {
    return 42
}
func init() {
    WhatIsThe = 0
}
func main() {
    if WhatIsThe == 0 {
        fmt.Println("It's all a lie.")
    }
}In this scenario, you’ll see that AnswerToLife() will run before our init()function as our WhatIsThe variable is declared before our init() function is called.
Multiple Init Functions in the Same File
What happens if we have multiple init() functions within the same Go file? At first I didn’t think this was possible, but Go does indeed support having 2 separate init() functions within the one file.
These init() functions are again called in their respective order of declaration within the file:
package main
import "fmt"
// this variable is initialized first due to
// order of declaration
var initCounter int
func init() {
    fmt.Println("Called First in Order of Declaration")
    initCounter++
}
func init() {
    fmt.Println("Called second in order of declaration")
    initCounter++
}
func main() {
    fmt.Println("Does nothing of any significance")
    fmt.Printf("Init Counter: %d\n", initCounter)
}Now, when you run the above program, you should see the output look like so:
$ go run test.go
Called First in Order of Declaration
Called second in order of declaration
Does nothing of any significance
Init Counter: 2Pretty cool, huh? But what is this for? Why do we allow this? Well, for more complex systems, it allows us to break up complex initialization procedures into multiple, easier-to-digest init() functions. It essentially allows us to avoid having one monolithic code block in a single init() function which is always a good thing. The one caveat of this style is that you will have to take care when ensuring declaration order.
Conclusion
So this concludes the basic introduction to the world of init() functions. Once you’ve mastered the use of the package initialization, you may find it useful to master the art of structuring your Go based projects.
If you have any further questions or feedback, then please feel free to let me know in the comments section below!
go包中的init() 函数的更多相关文章
- golang中的init函数以及main函数
		首先我们看一个例子:init函数: init 函数可在package main中,可在其他package中,可在同一个package中出现多次. main函数 main 函数只能在package ma ... 
- R语言:利用caret包中的dummyVars函数进行虚拟变量处理
		dummyVars函数:dummyVars creates a full set of dummy variables (i.e. less than full rank parameterizati ... 
- Go中的Init函数
		init函数会在main函数执行之前进行执行.init用在设置包.初始化变量或者其他要在程序运行前优先完成的引导工作. 举例:在进行数据库注册驱动的时候. 这里有init函数 package post ... 
- 使用RStudio调试(debug)基础学习(二)和fGarch包中的garchFit函数估计GARCH模型的原理和源码
		一.garchFit函数的参数--------------------------------------------- algorithm a string parameter that deter ... 
- 机器学习---笔记----numpy和math包中的常用函数
		本文只是简单罗列一下再机器学习过程中遇到的常用的数学函数. 1. math.fabs(x): 返回x的绝对值.同numpy. >>> import numpy >>> ... 
- go语言中strings包中的Trim函数的作用是什么
		答:Trim函数原型如下: func Trim(s string, cutset string) string 去掉字符串s中首部以及尾部与字符串cutset中每个相匹配的字符,如: s=" ... 
- Spark Submit给jar包中的main函数传递参数
		1 示范 spark-submit --master xxx demo.jar "arg1" "arg2" 运行的jar包和传参放在最后,就可以了 
- [转]go中的main函数和init函数
		Go里面有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main).这两个函数在定义时不能有任何的参数和返回值.虽然一个package里面可以 ... 
- Go中的main函数和init函数
		Go里面有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main).这两个函数在定义时不能有任何的参数和返回值.虽然一个package里面可以 ... 
随机推荐
- Git速成学习第二课:管理修改与删除文件
			Git速成学习笔记整理于廖雪峰老师的官网网站:https://www.liaoxuefeng.com/ 管理修改 首先我们需要明确,为什么说Git管理的是修改而不是文件呢? 我们首先对于已有的read ... 
- linux 系统自签免费ssl证书和nginx配置
			首先执行如下命令生成一个key openssl genrsa -des3 -out ssl.key 1024 然后他会要求你输入这个key文件的密码.不推荐输入.因为以后要给nginx使用.每次rel ... 
- JAVA日常之四
			构造函数 又称“构建器”,函数名称与类名称完全相同,无返回值. 每个类都有构造函数. 可以自定义构造函数,并且可以创建多个重载/过载的构造函数. 若没有手动创建该函数,总会存在一个默认的构造函数(无参 ... 
- Python Excel文件的读写操作(xlwt xlrd xlsxwriter)
			转:https://www.cnblogs.com/ultimateWorld/p/8309197.html Python语法简洁清晰,作为工作中常用的开发语言还是很强大的(废话). python关于 ... 
- pycharm配置git版本管理
			1.下载并安装git 首先你电脑必须安装git版本控制器(软件),在官网下载即可 2.安装git,正常安装即可 编缉器的选择,根据电脑实际情况选择合适的编缉器 安装参考:https://www.cnb ... 
- Python实现八大排序(基数排序、归并排序、堆排序、简单选择排序、直接插入排序、希尔排序、快速排序、冒泡排序)
			目录 八大排序 基数排序 归并排序 堆排序 简单选择排序 直接插入排序 希尔排序 快速排序 冒泡排序 时间测试 八大排序 大概了解了一下八大排序,发现排序方法的难易程度相差很多,相应的,他们计算同一列 ... 
- 关于greenlet的一些问题
			今天测试关于协程方面的代码发现我安装了greenlet模块缺导入不进.如图: 后来找了半天才发现原来greenlet被整进了gevent包中,如下导入就可以成功: 但这个greenlet没有了swit ... 
- c c++各种类型的取值范围
			int类型的变量存储值从-2147483648到2147483647 //例子 #include <iostream> using namespace std; int main(void ... 
- 一文让你明白Redis持久化
			网上虽然已经有很多类似的介绍了,但我还是自己总结归纳了一下,自认为内容和细节都是比较齐全的. 文章篇幅有 4k 多字,货有点干,断断续续写了好几天,希望对大家有帮助.不出意外地话,今后会陆续更新 Re ... 
- Python 正则表达模块详解
			Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ... 
