何时使用os.Exit()和panic()?


92

可能有人解释之间的关键差异os.Exit(),并panic()和它们是如何在实践中去使用?


11
只是有希望对将来的Go代码阅读有所帮助的注释:在许多示例代码中,panic由于错误易于理解,并且避免导入任何其他软件包,因此常用于错误退出。这并不意味着它是好的,还是惯用的做法!。它只是示例代码节省空间的设备。IRL储备panic用于非常特殊的情况。
Intermernet

1
嗯..好)特别是“ IRL”的缩写-对我来说是新的:)您能解释一下恐慌如何消除软件包导入吗?
Timur Fayzrakhmanov 2015年

4
panic是内置的。它的建议(视情况)使用类似os.Exitlog.Fatal等等,这将返回错误代码操作系统(总是建议如果可能的话)。这些都涉及导入包,从而“整理”示例代码。示例代码应始终仅用于说明特定问题的解决方案。该代码可能还存在其他问题,如果正确演示,它们会使代码变得更加复杂,因此有损于给出答案的解释。YMMV。
Intermernet

1
好,知道了!)非常感谢)我看到我的词汇还有另一个缩写:)
Timur Fayzrakhmanov 2015年

2
NP,很乐意为您提供帮助,并增加您的首字母
缩略词

Answers:


84

首先,每当您遇到“如何在实践中使用它”问题时,一个好的开始方法就是搜索 Go源代码(或实际上足够大的Go代码库),并在软件包文档中寻找答案。

现在,os.Exitpanic有很大的不同。panic当程序或其部分达到不可恢复的状态时使用。

panic被调用时(包括对运行时错误的隐式调用,例如,对切片进行索引编制索引或失败类型声明),它将立即停止当前函数的执行并开始展开goroutine的堆栈,并在此过程中运行所有延迟函数。如果解散到达goroutine堆栈的顶部,程序将终止。

os.Exit当您需要立即中止程序无法恢复或运行延迟的清除语句,并且还返回错误代码(其他程序可以用来报告发生的情况)时,使用。这在测试中很有用,当您已经知道一个测试失败后,另一个测试也会失败,因此您最好立即退出。当您的程序完成了它需要做的所有事情后,现在只需要退出,即在打印帮助消息之后,也可以使用此方法。

大多数情况下,您将不使用panic(应返回一个error替代值),并且几乎不需要os.Exit在某些情况下进行测试和快速终止程序。


9
“这在测试中很有用,当您已经知道一个测试失败后,另一个测试也会失败……”这散发出一种依赖测试的测试反模式的味道。在编写良好的测试套件中,每个测试都是独立的。任何给定测试的结果都不应决定其他任何测试的结果。
gotgenes

1
@gotgenes不一定。如果我有某个函数返回非nil结构的测试,并且该测试失败,那么我可以期望所有检查该结构值的测试也将失败。是代码,而不是测试。(也就是说,我不会exit在这种情况下使用,我只是期望
一大堆

83

首先,os.Exit()可以用来正常退出程序而不会出现错误,而不必惊慌,所以这是一个关键的区别。另一个是可以使用捕获并忽略或记录恐慌recover

但是,如果我们谈论的是错误的退出代码,可以这样说:

使用panic当出现可怕的错误,或许应该才去生产已陷入一个程序员的错误。这就是为什么它打印堆栈的原因。

os.Exit(errorCode)如果需要,请使用或类似的方法:

  1. 为脚本目的控制程序的退出代码。

  2. 希望在预期的错误(例如,用户输入错误)上有序退出。

因此,基本上来说,您感到恐慌,而错误的退出代码则对您的用户而言。


感谢您的帮助!)
Timur Fayzrakhmanov 2015年

14
“所以基本上,您感到恐慌,而错误的退出代码则适合您的用户。” <-很棒的提示
psousa

1
我们能否说panic()与普通C语言中通常的assert()调用相关?好吧..我知道我总是在推向生产之前删除断言调用,只有在测试新功能时才启用它们。我的意思是,大多数时候我都使用assert()来验证我认为必须在代码中成立的不变量。您看到panic()的用法相同吗?:-)
伊夫·波美

7

关键区别在于:

  1. os.Exit 跳过延迟功能的执行。
  2. 使用os.Exit,您可以指定退出代码。
  3. panic终止而os.Exit并非终止。(似乎其他答案没有提及。)

如果您需要执行延迟功能,则别无选择panic。(另一方面,如果要跳过延迟功能的执行,请使用os.Exit。)

如果以这种方式定义了非无效函数:

  1. 函数包含很多分支
  2. 所有分支均以return或终止panic

然后,您将无法替换为panicos.Exit否则编译器将拒绝编译该程序,并说“缺少函数结尾的返回”。(即使在这里,去也很笨log.Panic没有终止功能。)

在其他情况下:

  1. panic时的东西真的发生了连线,如编程逻辑错误。
  2. 使用os.Exit时,你要立即退出,与指定的退出代码。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.