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

Tim*_*nov 86 exit go

有人可以解释Go 之间的关键差异os.Exit()以及panic()它们在实践中的使用方式吗?

Not*_*fer 77

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

但是如果我们谈论错误的退出代码,那么让我们说:

panic当出现可怕的错误时使用,可能是程序员错误,应该在进入生产之前被捕获.这就是它打印堆栈的原因.

os.Exit(errorCode)如果您想要使用或类似的东西:

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

  2. 想要在预期的错误上有序退出(例如用户输入错误).

所以基本上恐慌是你的,一个糟糕的退出代码是为您的用户.

  • "所以基本上恐慌是为了你,一个糟糕的退出代码是为你的用户." < - 很棒的提示 (12认同)

Ain*_*r-G 73

首先,无论何时你有"如何在实践中使用"的问题,一个好的方法是搜索 Go源代码(或者任何足够大的Go代码库,真的),以及包文档以获得答案.

现在,os.Exit并且panic完全不同.panic当程序或其部分达到不可恢复状态时使用.

panic调用时,包含隐式的运行时错误,例如将切片索引越界或失败类型断言,它会立即停止执行当前函数并开始展开goroutine的堆栈,沿途运行任何延迟函数.如果该展开到达goroutine堆栈的顶部,则程序将死亡.

os.Exit当你需要立即中止程序,没有恢复或运行延迟清理语句的可能性时使用,并返回错误代码(其他程序可以用来报告发生的事情).这在测试中很有用,当你已经知道在一次测试失败后,另一次测试也会失败,所以你现在也可以退出.当你的程序完成了它需要做的所有事情时,也可以使用它,现在只需要退出,即在打印帮助信息之后.

大多数时候你不会使用panic(你应该返回一个error),而且你几乎不需要os.Exit在测试之外的某些情况以及快速程序终止.

  • "这在测试中非常有用,当你已经知道在这一次测试失败后,另一次测试失败了......"这就是依赖测试的反模式测试的气味.在一个编写良好的测试套件中,每个测试都是独立的; 任何给定测试的结果都不应该决定任何其他测试的结果. (8认同)
  • @gotgenes 不一定。如果我有一个测试,某个函数返回一个非零结构,并且该测试失败,那么我可以预期所有检查该结构值的测试也将失败。依赖的是代码,而不是测试。(也就是说,在这种情况下我不会使用“exit”,我只是期望一大堆失败的断言。) (3认同)

wea*_*ish 10

主要区别是:

  1. os.Exit 跳过延迟函数的执行。
  2. 使用os.Exit,您可以指定退出代码。
  3. panic正在终止而os.Exit不是。(似乎其他答案没有提到这一点。)

如果你需要执行延迟函数,你别无选择,只能panic. (另一方面,如果您想跳过延迟函数的执行,请使用os.Exit.)

如果以这种方式定义非空函数:

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

那么你不能用替换panicos.Exit否则编译器会拒绝编译程序,说“在函数结束时缺少返回”。(Go 在这里非常愚蠢,甚至log.Panic不终止函数。)

在其他条件下:

  1. 使用panic时的东西真的发生了连线,如编程逻辑错误。
  2. 使用os.Exit时,你要立即退出,与指定的退出代码。