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

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

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

我还读了Mark Summerfield的书:

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

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


当前回答

这里是另一个例子- https://play.golang.org/p/9P-LmSkUMKY

package main

import (
    "fmt"
)

func callOut() int {
    fmt.Println("Outside is beinge executed")
    return 1
}

var test = callOut()

func init() {
    fmt.Println("Init3 is being executed")
}

func init() {
    fmt.Println("Init is being executed")
}

func init() {
    fmt.Println("Init2 is being executed")
}

func main() {
    fmt.Println("Do your thing !")
}

上面程序的输出

$ go run init/init.go
Outside is being executed
Init3 is being executed
Init is being executed
Init2 is being executed
Do your thing !

其他回答

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

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

还有一些建议:

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

补充一点(我本可以作为评论添加的,但在写这篇文章的时候,我还没有足够的声誉)

在同一个包中有多个初始化,我还没有找到任何保证的方法来知道它们将以什么顺序运行。例如,我有:

package config
    - config.go
    - router.go

这两个配置。去找路由器吧。Go包含init()函数,但当运行router。Go的函数先运行(这导致我的应用程序恐慌)。

如果您有多个文件,每个文件都有自己的init()函数,请注意不能保证一个文件先于另一个文件。最好使用变量赋值,就像OneToOne在他的例子中展示的那样。最好的部分是:这个变量声明将发生在包中的ALL init()函数之前。

例如

config.go:

var ConfigSuccess = configureApplication()

func init() {
    doSomething()
}

func configureApplication() bool {
    l4g.Info("Configuring application...")
    if valid := loadCommandLineFlags(); !valid {
        l4g.Critical("Failed to load Command Line Flags")
        return false
    }
    return true
}

router.go:

func init() {
    var (
        rwd string
        tmp string
        ok  bool
    )
    if metapath, ok := Config["fs"]["metapath"].(string); ok {
        var err error
        Conn, err = services.NewConnection(metapath + "/metadata.db")
        if err != nil {
            panic(err)
        }
    }
}

不管var ConfigSuccess = configureApplication()是否存在于路由器中。Go或config。go,它将在EITHER init()运行之前运行。

https://golang.org/ref/mem#tmp_4

程序初始化在单个goroutine中运行,但该goroutine可以创建其他goroutine,这些goroutine可以并发运行。 如果包p导入包q, q的初始化函数的完成发生在p的任何初始化函数开始之前。 函数main的开始。Main发生在所有init函数完成之后。

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

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