GAE Go,init() - 多次调用它?

时间:2012-01-30 03:50:09

标签: http google-app-engine initialization admin go

我正在撰写Google App Engine Go应用程序。在其中,我想在不同的.go文件中分别处理一些调用。我应该在每个文件中单独调用“init()”函数,还是只在一个文件中声明它并调用其他函数来初始化每个.go文件?

例如,如果我有两个文件,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!")
}

和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!")
}

这样的初始化是正确的,还是建议不要这样做?

2 个答案:

答案 0 :(得分:10)

根据Go语言规范:

  • 所有初始化代码都在一个goroutine中运行,

  • 单个包中的init()函数以未指定的顺序执行

在您的情况下,用户和管理员包是独立的(用户不导入管理员,也不管理导入用户)。这意味着:

  • User和Admin中的两个init()函数以未指定的顺序执行

在单个init()函数中连接两个init()函数的主体将如下所示:

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

请注意,程序是先注册"/"还是"/admin/"无关紧要。因此,以下代码也有效:

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

从上面两段代码中,我们可以看到http.HandleFunc("/", ...)http.HandleFunc("/admin/", ...)以未指定的顺序调用是可以的。


由于"/""/admin/"可以按任何顺序注册,并且所有init()函数都在单个goroutine中运行,因此您的问题的答案是:是的,这样的初始化正确

答案 1 :(得分:1)

我认为您的问题实际上是包装设计之一。我无法用你的问题说出来,但你也可能会混淆包和源文件。澄清一下:一个包由一个目录中的一个或多个源文件组成,定义了一个逻辑功能单元,包括公共API和数据的私有内部表示。

如果您对init()的细节感兴趣,请参阅规范

的相关部分
  

通过分配初始值来初始化没有导入的包   到它的所有包级变量,然后调用任何包级别   具有

的名称和签名的函数      

func init()

     

在其来源中定义。

您在上面的代码中定义了两个包,因此以下内容也适用:

  

如果包具有导入,则之前初始化导入的包   初始化包本身。

这表明Admin是否依赖于User(反之亦然),这将决定执行两个init()调用的顺序。没有这种依赖会导致以未指定的顺序执行init()调用。

但是,考虑到您拥有的代码,您并不关心它们执行的顺序。所以真的归结为你是否真的需要两个包,或者你是否可以使用一个包(可能有两个独立的源文件)。

您可能会问自己一些问题:

  • 是否有两个独立的(业务)函数可供表示?
  • 您是否需要提供单独的公共API?
  • 分离不同包(不同编码器)的任何组织原因?
  • 您是否计划在一个或多个包中重复使用代码?