我正在撰写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!")
}
这样的初始化是正确的,还是建议不要这样做?
答案 0 :(得分:10)
根据Go语言规范:
所有初始化代码都在一个goroutine中运行,
单个包中的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()调用。
但是,考虑到您拥有的代码,您并不关心它们执行的顺序。所以真的归结为你是否真的需要两个包,或者你是否可以使用一个包(可能有两个独立的源文件)。
您可能会问自己一些问题: