golang在一个包中允许多个init的目的是什么?

时间:2017-07-24 10:44:40

标签: go init

我知道golang允许在一个包中使用多个init,甚至在一个文件中。 我想知道为什么? 例如,如果一个pkg有很多文件,我们可以写多个init然后我们可能会丢失我们应该把init放到哪里,如果我们在一个pkg中有多个init,我们也会对init命令感到困惑。 (我的意思是这更好吗?我们只能有1个init,然后我们可以有一些initXXX,然后把它们放到init中,看起来很干净。) 在代码结构视图中执行此操作的优点是什么?

2 个答案:

答案 0 :(得分:10)

这个问题可能有点基于意见,但使用多个包init()函数可以使您的代码更易于阅读和维护。

如果源文件很大,通常按照某种逻辑顺序排列其内容(例如类型,变量声明,方法等)。允许多个init()函数使您可以将初始化代码放在它们应该初始化的部分附近。如果不允许这样做,你将被迫每个包使用一个init()函数,并将所有内容放入其中,远离它们初始化所需的变量。

是的,拥有多个init()函数可能需要关注执行顺序,但要知道使用多个init()函数不是必需的,它只是一种可能性。并且您可以将init()函数写入没有" side"效果,不依赖于其他init()函数的完成。

如果这是不可避免的,你可以创建一个" master" init()明确控制其他孩子的顺序" init()函数。

"主人的一个例子" init()控制其他初始化函数:

func init() {
    initA()
    initB()
}

func initA() {}
func initB() {}

在上面的示例中,initA()将始终在initB()之前运行。

规范中的相关部分:Package initialization

另请参阅相关问题:What does lexical file name order mean?

答案 1 :(得分:0)

多个init()函数的另一个用例是基于构建标记添加功能。 init()函数可用于将钩子添加到现有包中并扩展其功能。

以下是一个精简示例,演示了基于构建标签向CLI实用程序添加更多命令的过程。

package main

import "github.com/spf13/cobra"

var (
    rootCmd = &cobra.Command{Use: "foo", Short: "foo"}
)

func main() {
    rootCmd.AddCommand(
        &cobra.Command{Use: "CMD1", Short: "Command1"},
        &cobra.Command{Use: "CMD1", Short: "Command1"},
    )
    rootCmd.Execute()
}

以上是该实用工具的“原始”版本。

// +build debugcommands

package main

import "github.com/spf13/cobra"

func init() {
    rootCmd.AddCommand(&cobra.Command{Use: "DEBUG-CMD1", Short: "Debug command1"})
}

第二个文件的内容扩展了标准命令,并附加了在开发过程中最相关的其他命令。

使用go build -tags debugcommands进行编译将生成带有已添加命令的二进制文件,而省略-tags标志将生成标准版本。