美文网首页
Golang中的init函数

Golang中的init函数

作者: ShootHzj | 来源:发表于2021-06-23 22:17 被阅读0次

翻译自

正文

init函数在包中定义,通常用来

  • 比较复杂的初始化流程,不能通过表达式初始化的变量的初始化
  • 检查、修复程序的状态
  • 注册
  • 执行一次性的计算
  • 等等

除了下面讨论的一些差异之外,init函数中可以放任何常规函数可以放的东西

包初始化

要使用导入的包,需要先将包初始化,初始化及顺序问题由Golang的running system完成。

  • 导入的包的初始化(递归定义)
  • 为包中声明的变量计算和分配初始值
  • 执行包中的init函数
即使包被导入多次,包的初始化也只能执行一次

顺序

Go里面的一个包可以包含多个文件。分布在众多包中的众多文件,变量和init函数执行的顺序应该是什么样子呢?之前的文章提到了变量的初始化顺序。完成此操作后,需要决定文件 a.goz.go 中的变量初始化谁更应该早执行。 这取决于传递给编译器的文件顺序。 如果 z.go 首先由构建系统传递,则z.go先执行,然后在 a.go 的再执行。 这同样适用于init 函数的触发。 语言规范建议始终使用相同的顺序并按字典顺序从包中传递文件名:

为了确保可重现的初始化行为,鼓励构建系统把属于同一包的多个文件以词法文件名顺序传递给编译器。

不过依赖文件名初始化顺序的程序十分罕见,让我们来看这样子的例子

sandbox.go

package main
import "fmt"
var _ int64 = s()
func init() {
    fmt.Println("init in sandbox.go")
}
func s() int64 {
    fmt.Println("calling s() in sandbox.go")
    return 1
}
func main() {
    fmt.Println("main")
}

a.go

package main
import "fmt"
var _ int64 = a()
func init() {
    fmt.Println("init in a.go")
}
func a() int64 {
    fmt.Println("calling a() in a.go")
    return 2
}

.go

package main
import "fmt"
var _ int64 = z()
func init() {
    fmt.Println("init in z.go")
}
func z() int64 {
    fmt.Println("calling z() in z.go")
    return 3
}

运行后,程序会这样输出

calling a() in a.go
calling s() in sandbox.go
calling z() in z.go
init in a.go
init in sandbox.go
init in z.go
main

属性

init函数不需要参数也不返回任何值。和main不同,标识符init未声明,所以不能被引用

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

在编译时,程序返回

undefined: init

同一个包或文件中可以有很多个init函数,在不同文件中定义的init函数如下按照字母顺序执行,同一个文件按声明顺序执行,举例

sandbox.go

package main
import "fmt"
func init() {
    fmt.Println("init 1")
}
func init() {
    fmt.Println("init 2")
}
func main() {
    fmt.Println("main")
}

utils.go

package main
import "fmt"
func init() {
    fmt.Println("init 3")
}

输出

init 1
init 2
init 3
main

init函数的最常见用途,就是用来给那些不能通过表达式初始化的变量初始化,如:

var precomputed = [20]float64{}
func init() {
    var current float64 = 1
    precomputed[0] = current
    for i := 1; i < len(precomputed); i++ {
        precomputed[i] = precomputed[i-1] * 1.2
    }
}

表达式中可不能使用for循环,所以通过init函数来解决这个问题

为了副作用来导入包

Go对于未使用的引用非常严格。有些场景,你导入一个包,只为了执行其中的init函数(如mysql的driver)。

import _ "image/png"

相关文章

  • Golang中的init函数

    翻译自 https://medium.com/golangspec/init-functions-in-go-ea...

  • golang中特殊的init函数

    一、package 和init函数 package组织go代码的一种形式,和python ,Java,c++等语言...

  • golang init函数

    go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性, 有下面的特征: 下面的两...

  • Golang的init函数

    Golang的init函数 转载:https://zhuanlan.zhihu.com/p/34211611 大家...

  • golang package init 可以多处定义

    在 golang 中 import 包 A 的时候,会自动隐式的调用该包A的 init() 函数。 调用顺序:如果...

  • golang init()函数详解

    一、每个包都可以一个或多个init()函数即 每个源⽂件都可以定义⼀个或多个初始化函数 二、执行顺序问题1、同一个...

  • Golang的Init函数和Main函数

    Init函数和main函数 go语言中的init函数用于包package初始化。该函数时go语言的一个重要特性in...

  • golang的main及init函数

    转自:https://blog.csdn.net/rznice/article/details/18987047G...

  • init()函数 先导入的包的init函数先执行 init()函数和main()函数 这两个函数都是go中的保留函...

  • Golang重要特征之init函数

    go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性 inti函数主要特征: 1...

网友评论

      本文标题:Golang中的init函数

      本文链接:https://www.haomeiwen.com/subject/qteiyltx.html