Import 在Golang中导入模块时如何捕获错误?

Import 在Golang中导入模块时如何捕获错误?,import,go,Import,Go,在golang中,当我导入一个模块时,它的init()被执行(在我假设的main()之前?),这个函数中可能会产生一些错误。如何捕获这些错误并在自己的代码中处理它们?您可能知道,Go中的错误是返回值。由于init()不返回任何内容,如果出现任何错误,唯一的替代方法是在init中使用panic() 一个在init上陷入恐慌的包可以说设计得不是很好,尽管可能存在有效的用例 在这种情况下,recover()不是一个选项,因为init在main之前运行。因此,如果你不能编辑有问题的包,那么你就不走运了

在golang中,当我导入一个模块时,它的init()被执行(在我假设的main()之前?),这个函数中可能会产生一些错误。如何捕获这些错误并在自己的代码中处理它们?

您可能知道,Go中的错误是返回值。由于init()不返回任何内容,如果出现任何错误,唯一的替代方法是在init中使用panic()

一个在init上陷入恐慌的包可以说设计得不是很好,尽管可能存在有效的用例

在这种情况下,recover()不是一个选项,因为init在main之前运行。因此,如果你不能编辑有问题的包,那么你就不走运了

这就是为什么恐慌和恢复应该谨慎使用的原因之一,只有在字面上“恐慌”才有意义的情况下

@Twowo从“有效的Go”中引用了以下描述(对于init案例):

如果图书馆真的无法自立,可以说,恐慌是合理的

所以:如果您的init函数需要报告一个错误,那么问问自己,该代码是否真的属于init,或者最好保存在其他地方。如果真的必须是init,考虑在包内设置一个错误标志,并记录任何客户端必须检查该错误。

< P>是,包<代码> init()<代码>函数运行在主()/<代码>函数之前,请参见语言规范。

不,您无法处理包
init()函数中发生的错误。即使可以,这也意味着程序所依赖的包无法初始化,您不知道从中可以得到什么

Package
init()
函数没有返回值,它们不能以一种有意义的方式死机,而这种死机本来是要从中恢复的。如果
init()
函数死机,程序将终止

由于
init()
函数不是由您调用的(例如从
main()
函数),因此无法从那里恢复。包本身负责在初始化期间处理错误,而不是包的用户


init()
期间发出错误信号的一个选项是将错误状态存储在变量中(例如,已导出或未导出但可由导出函数查询)。但是,只有在合理的情况下才能继续使用,这也是包本身的任务/责任(存储/报告错误),而不是包的用户。如果没有软件包的配合,您无法做到这一点(您无法“捕获”未处理/未报告的错误和恐慌)。

不能直接执行,但您可以使用以下方法:

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)
    }
    // ...
}

我理解你的想法,但有一个bug:
:=
将在init.IMO中声明一个本地
InitErr
,如果需要,最好转到显式控制的初始化。例如,
err:=mypkg.Init()
x,err:=mypkg.OpenSomething()。同意恐慌:“如果库确实无法自行设置,可以说恐慌是合理的。”谢谢,我的回答中包含了您的贡献。在我的情况下,我导入的模块需要某个特定路径的配置文件,如果该文件不存在,它会恐慌。我想捕获错误(不可能)并记录日志,或者在别处提供回退配置文件。我可以更改conf file变量并重新调用init()函数吗?@NeoWang在程序所依赖的包
init()函数完成之前,您不能执行任何操作。您可以更改外部包的
init()
函数。但是如果包是这样写的,并且您不能或不想修改包源文件,那么您唯一能做的就是在启动应用程序之前确保预期的配置文件存在。@NeoWang如果是我,我要么请求上游更改,要么分叉包以允许类似于
err:=thirdPartyPackage.Config(filename/or/reader)
的内容,或者至少有一个环境变量来覆盖位置。根据第三方软件包是什么/做什么,拥有一个API,其中包含一个静态定位的配置文件,该文件需要存在(并且可能还包含“正确”的内容),以便启动其他人的程序,这是一个糟糕的设计。