我试图找到一个关于init()函数在Go中的作用的精确解释。我读了Effective Go说的话,但我不确定我是否完全理解了它说的话。我不太确定的句子是:

finally的意思是最后:init是在包中所有变量声明都计算了它们的初始化式之后调用的,并且只有在所有导入的包都初始化之后才会计算这些初始化式。

包中所有变量声明对其初始化式求值意味着什么?这是否意味着如果你在一个包和它的文件中声明“全局”变量,init()将不会运行,直到所有的它被评估,然后它将运行所有的init函数,然后main()当。/main_file_name运行?

我还读了Mark Summerfield的书:

如果一个包有一个或多个init()函数,它们会在主包的main()函数被调用之前自动执行。

在我的理解中,init()只在您打算运行main()时才相关,对吗?如果有人更清楚地理解init(),请随意纠正我


当前回答

看这张照片。:)

导入——> const——> var——> init()

如果一个包导入了其他包,则首先初始化导入的包。 当前包的常量初始化。 然后初始化当前包的变量。 最后,调用当前包的init()函数。

一个包可以有多个init函数(可以在单个文件中,也可以分布在多个文件中),并且按照它们呈现给编译器的顺序调用它们。

一个包只能被初始化一次,即使它是从多个包中导入的。

其他回答

在一个包中混合init函数执行顺序:

Const和变量定义的文件init()函数执行 初始化函数按文件名asc执行

Init将在任何使用它的包的地方被调用(无论是空白导入还是导入),但只有一次。

这是一个包:

package demo

import (
    "some/logs"
)

var count int

func init() {
    logs.Debug(count)
}

// Do do
func Do() {
    logs.Debug("dd")
}

任何包(主包或任何测试包)作为空白导入:

_ "printfcoder.com/we/models/demo"

或者使用it func导入它:

"printfcoder.com/we/models/demo"

func someFunc(){
   demo.Do()
}

init将只记录一次日志0。 第一个使用它的包,它的init func将在包的init之前运行。所以:

A调用B B调用C,它们都有init func, C的init会在B之前运行,B在A之前运行。

是的,假设你有这个:

var WhatIsThe = AnswerToLife()

func AnswerToLife() int { // 1
    return 42
}

func init() { // 2
    WhatIsThe = 0
}

func main() { // 3
    if WhatIsThe == 0 {
        fmt.Println("It's all a lie.")
    }
}

AnswerToLife()保证在调用init()之前运行,并且init()保证在调用main()之前运行。

请记住,init()总是被调用,无论是否有main,所以如果你导入一个包,它有init函数,它将被执行。

此外,每个包可以有多个init()函数;它们将按照它们在文件中出现的顺序执行(当然是在所有变量初始化之后)。如果它们跨越多个文件,它们将按照词法文件名的顺序执行(正如@benc指出的那样):

init()函数似乎是按词法文件名顺序执行的。Go规范说:“构建系统被鼓励以词法文件名的顺序将属于同一个包的多个文件呈现给编译器”。似乎go build是这样工作的。


许多内部Go包使用init()来初始化表等,例如https://github.com/golang/go/blob/883bc6/src/compress/bzip2/bzip2.go#L480

还有一些建议:

只能有一个main()函数,但可以有很多init()函数。 你不需要显式地调用init()或main(),它们会自动调用。 Init()和main()不接受任何参数,也不返回任何东西。 Init()在main()之前运行。 如果你有很多init(),它们会按照声明的顺序运行。

init func首先运行,然后是main。它用于在程序运行之前先设置一些东西,例如:

访问模板, 使用所有核心运行程序, 检查Goos和arch等…