在 Golang 中导入模块时如何捕获错误?
How to capture errors when importing a module in Golang?
在 golang 中,当我导入一个模块时,它的 init() 被执行(我假设在 main() 之前?),这个函数中可能会产生一些错误。我如何捕获这些错误并在我自己的代码中处理它们?
Go 中的错误是 return 个值,您可能知道。由于 init() 没有 return 任何东西,如果出现任何问题,唯一的选择是在 init 中使用 panic()。
在 init 时出现恐慌的包可以说设计得不是很好,尽管可能有有效的用例。
在这种情况下,recover() 不是一个选项,因为 init 在 main 之前 运行。所以如果你不能编辑有问题的包,那你就倒霉了。
这就是为什么应谨慎使用 panic 和 recover 的原因之一,仅在字面上 "panicking" 有意义的情况下使用。
@twotwotwo 从 "effective Go" 引用了以下引述(对于初始情况):
if the library truly cannot set itself up, it might be reasonable to panic, so to speak
因此:如果您的 init 函数需要报告错误,那么问问自己该代码是否真的属于 init 或最好保存在其他地方。如果它确实必须是 init,请考虑在包内设置一个错误标志,并记录任何客户端必须检查该错误。
是的,在 main()
函数之前封装 init()
函数 运行,请参阅语言规范中的 Package initialization。
不,您不能处理包 init()
函数中发生的错误。即使你可以,那也意味着你的程序依赖的包无法初始化,你不知道它会带来什么。
包 init()
函数没有 return 值,它们不会以有意义的方式发生恐慌,这意味着可以从中恢复。如果 init()
函数崩溃,程序将终止。
由于您未调用 init()
函数(例如从 main()
函数调用),因此您无法从那里恢复。在初始化过程中处理错误是包本身的责任,而不是包的用户。
在 init()
期间发出错误信号的一个选项是将错误状态存储在变量中(例如已导出,或未导出但可由导出函数查询)。但这只有在合理继续时才应该使用,这也是包本身的task/responsibility(到store/report错误)而不是包的用户。没有包的配合你做不到这一点(你不能"catch"unhandled/unreported错误和恐慌)。
不是直接的,但你可以使用这样的东西:
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)
}
// ...
}
在 golang 中,当我导入一个模块时,它的 init() 被执行(我假设在 main() 之前?),这个函数中可能会产生一些错误。我如何捕获这些错误并在我自己的代码中处理它们?
Go 中的错误是 return 个值,您可能知道。由于 init() 没有 return 任何东西,如果出现任何问题,唯一的选择是在 init 中使用 panic()。
在 init 时出现恐慌的包可以说设计得不是很好,尽管可能有有效的用例。
在这种情况下,recover() 不是一个选项,因为 init 在 main 之前 运行。所以如果你不能编辑有问题的包,那你就倒霉了。
这就是为什么应谨慎使用 panic 和 recover 的原因之一,仅在字面上 "panicking" 有意义的情况下使用。
@twotwotwo 从 "effective Go" 引用了以下引述(对于初始情况):
if the library truly cannot set itself up, it might be reasonable to panic, so to speak
因此:如果您的 init 函数需要报告错误,那么问问自己该代码是否真的属于 init 或最好保存在其他地方。如果它确实必须是 init,请考虑在包内设置一个错误标志,并记录任何客户端必须检查该错误。
是的,在 main()
函数之前封装 init()
函数 运行,请参阅语言规范中的 Package initialization。
不,您不能处理包 init()
函数中发生的错误。即使你可以,那也意味着你的程序依赖的包无法初始化,你不知道它会带来什么。
包 init()
函数没有 return 值,它们不会以有意义的方式发生恐慌,这意味着可以从中恢复。如果 init()
函数崩溃,程序将终止。
由于您未调用 init()
函数(例如从 main()
函数调用),因此您无法从那里恢复。在初始化过程中处理错误是包本身的责任,而不是包的用户。
在 init()
期间发出错误信号的一个选项是将错误状态存储在变量中(例如已导出,或未导出但可由导出函数查询)。但这只有在合理继续时才应该使用,这也是包本身的task/responsibility(到store/report错误)而不是包的用户。没有包的配合你做不到这一点(你不能"catch"unhandled/unreported错误和恐慌)。
不是直接的,但你可以使用这样的东西:
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)
}
// ...
}