在golang中,当我导入一个模块时,它的init()被执行(在我假设的main()之前?),这个函数可能会产生一些错误。如何捕获这些错误并在我自己的代码中处理它们?
答案 0 :(得分:4)
Go中的错误是返回值,您可能知道。由于init()不返回任何内容,唯一的选择是在init中出现panic(),如果出现任何问题。
在init上发生恐慌的软件包可能没有很好的设计,尽管可能存在有效的用例。
鉴于这种情况,recover()不是一个选项,因为init在main之前运行。所以如果你不能编辑有问题的包,那你就不走运了。
这是为什么应该谨慎使用恐慌和恢复的原因之一,只有在字面上“恐慌”才有意义的情况下。
@twotwotwo从“有效Go”中提供了以下引用,描述了这一点(对于init案例):
如果图书馆真的无法自我设定,恐慌可能是合理的,可以这么说
所以:如果您的init函数需要报告错误,那么问问自己该代码是否真的属于init,或者更好地保存在其他地方。如果它确实必须是init,请考虑在包内设置一个错误标志,并记录任何客户端必须检查该错误。
答案 1 :(得分:2)
是的,包init()
函数在main()
函数之前运行,请参阅语言规范中的Package initialization。
不,您无法处理包init()
函数中发生的错误。即使你可以,这也意味着你的程序所依赖的软件包无法初始化,你也不会知道该对它有什么期望。
包init()
个函数没有返回值,并且它们无法以有意义的方式从中恢复。如果init()
函数发生混乱,程序将终止。
由于您未调用init()
函数(例如来自main()
函数),因此无法从那里恢复。包本身有责任在初始化期间处理错误,而不是包的用户。
在init()
期间发出错误信号的一个选项是将错误状态存储在变量中(例如,导出或未导出但可由导出的函数查询)。但是只有在合理的情况下才能使用它,这也是包本身(存储/报告错误)的任务/责任,而不是包的用户。如果没有包的合作,你就无法做到这一点(你可以"捕获"未处理/未报告的错误和恐慌)。
答案 2 :(得分:1)
不是直接的,但你可以使用这样的东西:
package mypkg
var InitErr error
var Foo MyFoo
func init() {
Foo, InitErr = makeInitialisation()
// ...
}
然后在你的主要:
package main
import "foo/bar/mypkg"
func main() {
if (mypkg.InitErr != nil) {
panic(err)
}
// ...
}