本文很多东西都是源自网络,稍微整理了下,是否正确尚未验证,因此,有错误的话,请留言。
一、
main(),init()方法是go中默认的两个方法,两个保留的关键字。 init()方法 是在任何package中都可以出现,但是建议 每个package中只包含一个init()函数比较好,容易理解。 但是main() 方法只能用在package main 中。 Go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数。每个 package中的init函数都是可选的,但package main就必须包含一个main函数。 程序的初始化和执行都起始于main包。如果main包还导入了其它的包,那么就会在编译时 将它们依次导入。有时一个包会被多个包同时导入,那么它只会被导入一次(例如很多包可 能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。当一个包被导入时, 如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量 和变量进行初始化,接着执行init函数(如果有的话),依次类推。等所有被导入的包都加 载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的 init函数(如果存在的话),最后执行main函数
二、
go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性,
有下面的特征:
1 init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等
2 每个包可以拥有多个init函数
4 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)
5 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
6 init函数不能被其他函数调用,而是在main函数执行之前,自动被调用
下面这个示例摘自《the way to go》,os差异在应用程序初始化时被隐藏掉了,
var prompt = "Enter a digit,e.g. 3 " + "or %s to quit." func init() { if runtime.GOOS == "windows" { prompt = fmt.Sprintf(prompt,"Ctrl+Z,Enter") } else { // Unix-like prompt = fmt.Sprintf(prompt,"Ctrl+D") } }
下面的两个go文件演示了:
1 一个package或者是go文件可以包含多个init函数,
3 init函数被自动调用,不能在其他函数中调用,显式调用会报该函数未定义
gprog.go代码
package main import ( "fmt" ) // the other init function in this go source file func init() { fmt.Println("do in init") } func main() { fmt.Println("do in main") } func testf() { fmt.Println("do in testf") //if uncomment the next statment,then go build give error message : .\gprog.go:19: undefined: init //init() }
ginit1.go代码,注意这个源文件中有两个init函数
package main import ( "fmt" ) // the first init function in this go source file func init() { fmt.Println("do in init1") } // the second init function in this go source file func init() { fmt.Println("do in init2") }
编译上面两个文件:go build gprog.go ginit1.go
编译之后执行gprog.exe后的结果表明,gprog.go中的init函数先执行,然后执行了ginit1.go中的两个init函数,然后才执行main函数。
E:\opensource\go\prj\hellogo>gprog.exe do in init do in init1 do in init2 do in main
注:《the way to go》中(P70)有下面红色一句描述,意思是说一个go源文件只能有一个init函数,
但是上面的ginit1.go中的两个init函数编译运行后都正常执行了,
因此这句话应该是笔误。
4.4.5 Init-functions Apart from global declaration with initialization,variables can also be initialized in an init()-function. This is a special function with the name init() which cannot be called,but is executed automatically before the main() function in package main or at the start of the import of the package that contains it. Every source file can contain only 1 init()-function. Initialization is always single-threaded and package dependency guarantees correct execution order.
三、
作为一个golang新手,我们要写很多简单的golang代码,却又很想保留这些代码。
@H_404_84@ 可是写下一个小程序的时候又不得不注释掉一些代码,渐渐的main函数很乱,或者有很多入口。 @H_404_84@ 这里我介绍一种方法。即可以保留这些代码,又不会因为后续新增的代码导致他们很乱。 @H_404_84@ 用到了golang的一些特性: @H_404_84@ 1. 加载一个包时,会自动运行其中的init()方法,一个包可以定义多个init方法,而且每个init()方法都会被调用。 @H_404_84@ 2.import _ "xxxxx" 引入一个包,即使没调用里面的函数也不会报错,而且会执行其中的init()方法。 @H_404_84@ 这是我的main packagepackage main import _ "learn" func main(){ }@H_404_84@ 当然你直接保存运行上面代码,有learn包的话不会报错,运行良好。当然如果learn包不存在肯定会报错。 @H_404_84@ 如果我要写一个打印hello world!的小程序的话 我是这样做的: @H_404_84@ 在learn目录下建一个helloworld.go文件
package learn import "fmt" func init(){ // return fmt.Println("hello world!") }
@H_404_84@ 保存运行... 什么结果呢? @H_404_84@ 输出:hello world! @H_404_84@ 如果不想这段代码运行直接在init里面return就可以了 @H_404_84@ 这样每一个小程序一个文件,用init()代替了main()当做入口方法。是不是很方便呢?
参考文献:
http://blog.csdn.net/u011156212/article/details/45078189
http://blog.csdn.net/u011156212/article/details/45078323
http://www.cnblogs.com/youyou/archive/2013/04/21/3034211.html
http://my.oschina.net/yearnfar/blog/187278
原文链接:https://www.f2er.com/go/189669.html