GAE Go, init () - calling it several times?

I am writing a Google App Engine Go application. In it, I want to handle some calls separately in different .go files. Should I call the "init ()" function separately in each of these files, or simply declare it in a single file and call some other functions to initialize each .go file?

For example, if I have two files, user.go:

package User import( "http" "fmt" ) func init() { http.HandleFunc("/", hello) } func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, user!") } 

And admin.go:

 package Admin import( "http" "fmt" ) func init() { http.HandleFunc("/admin/", hello) } func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, admin!") } 

Is this initialization correct, or is it advised against something like that?

+4
source share
2 answers

According to the Go language specification:

  • all initialization code runs in one goroutine, and

  • The init () functions in a single package are executed in unspecified order.

In your case, the User and Admin packages are independent (the User does not import Admin, and Admin does not import the user). It means that:

  • two init () functions in User and Admin execute in unspecified order

The union of the bodies of two init () functions in one init () function will look like this:

 func init() { http.HandleFunc("/", User.Hello) http.HandleFunc("/admin/", Admin.Hello) } 

Please note that it doesn’t matter if the program first registers "/" or "/admin/" . Thus, the following code is valid:

 func init() { http.HandleFunc("/admin/", Admin.Hello) http.HandleFunc("/", User.Hello) } 

From the above two code snippets, we can see that OK http.HandleFunc("/", ...) and http.HandleFunc("/admin/", ...) should be called in an unspecified order.


Since "/" and "/admin/" can be registered in any order, and all init () functions are run in one goroutine, the answer to your question: Yes, this initialization is correct.

+10
source

I think your question is really one of the package design. I can’t say for your question, but you can also mislead packages and source files. To clarify: a package consists of one or more source files in one directory, defines a logical unit of functionality, including public APIs and private internal data representations.

If you are interested in the init () specification, here are the relevant parts of the specification

A package without import is initialized by assigning initial values ​​to all its package-level variables, and then calling any package-level function with a name and signature

func init ()

defined in its source.

You have two packages defined in your code above, so the following also applies:

If the package has import, the imported packages are initialized before the package itself is initialized.

Which tells you if there is an Admin dependency on the user (or vice versa) that will determine the order in which two init () calls are made. Such a dependency will not lead to init () calls in an unspecified order.

However, given the code that you have, you don't care what order they are executed. So really, it comes down to whether you really need two packages, or you can do with one package (possibly with two separate source files).

Some questions you can ask yourself:

  • Are there two separate (business functions) to represent?
  • Do you need to provide separate public APIs?
  • Any organizational reasons for separating different packets (different encoders)?
  • Are you planning to reuse the code in one or more packages independently of the other?
+1
source

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


All Articles