What is the purpose of golang allowing multiple init in one package?

I know that golang allows multiple init in one package and even in one file. I wonder why? For example, if there are many files in pkg, we could write several init, then we could get lost in where we should put init, and we can also be confused by the order of init, if we have several init in one pkg. (I mean, is this better? We can only have 1 init, then we can have some initXXX, and then put them in init, it looks pretty clean). What is the advantage of doing this in representing the code structure?

+11
source share
2 answers

This question may be opinion based, but using several of the init() package functions can make it easier to read and maintain your code.

If your source files are large, you usually place their contents (such as types, variable declarations, methods, etc.) in some logical order. Enabling multiple init() functions allows you to place the initialization code next to the parts that they must initialize. If this is not resolved, you will be forced to use one init() function for each package and put everything in it, away from the variables they need to initialize.

Yes, having multiple init() functions may require some care about the execution order, but be aware that using multiple init() functions is not a requirement, but just an opportunity. And you can write init() functions so that there are no "side" effects, so as not to rely on the completion of other init() functions.

If this is unavoidable, you can create one "master" init() that explicitly controls the order of the other, "child" init() functions.

An example of a "wizard" init() that manages other initialization functions:

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

In the above example, initA() will always work until initB() .

Relevant section from the specification: Initialization of the package .

See also the related question: What does the lexical order of file names mean?

+12
source

Another use case for several init() functions is to add functions based on assembly tags. The init() function can be used to add hooks to an existing package and extend its functionality.

The following is a concise example that demonstrates adding additional commands to the CLI utility based on assembly tags.

 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() } 

Above is the "vanilla" version of the utility.

 // +build debugcommands package main import "github.com/spf13/cobra" func init() { rootCmd.AddCommand(&cobra.Command{Use: "DEBUG-CMD1", Short: "Debug command1"}) } 

The contents of the second file extends the standard command with additional commands, which are mostly relevant during development.

Compiling using go build -tags debugcommands will create a binary file with added commands, while -tags flag will create a standard version.

0
source

Source: https://habr.com/ru/post/1270147/


All Articles