瑞安·戴维斯(Ryan Davis)的《Ruby QuickRef》说(没有解释):

不要拯救例外.曾经否则我会刺你.

为什么不呢?正确的做法是什么?

推荐答案

TL;DR:使用StandardError代替常规异常捕获.当重新引发原始异常时(例如,当救援仅记录异常时),救援Exception可能是可以的.


ExceptionRuby's exception hierarchy的根,所以当你rescue Exception时,你从everything中解救出来,包括SyntaxErrorLoadErrorInterrupt这样的子类.

救援Interrupt可防止用户使用CTRLC退出程序.

救援SignalException会阻止程序正确响应信号.除非到kill -9年,否则它将是无法解决的.

拯救SyntaxError意味着失败的eval将默默地这样做.

所有这些都可以通过运行此程序,并try 按CTRLCkill键来显示:

loop do
  begin
    sleep 1
    eval "djsakru3924r9eiuorwju3498 += 5u84fior8u8t4ruyf8ihiure"
  rescue Exception
    puts "I refuse to fail or be stopped!"
  end
end

Exception人中解救出来甚至不是默认情况.做

begin
  # iceberg!
rescue
  # lifeboats
end

不是从Exception拯救,而是从StandardError拯救.通常,您应该指定比默认的StandardError更具体的内容,但是从Exception broadens中拯救范围,而不是缩小范围,并且可能会产生灾难性的结果,使错误查找变得极其困难.


如果您确实希望从StandardError中拯救,并且需要一个变量(例外情况除外),您可以使用以下表格:

begin
  # iceberg!
rescue => e
  # lifeboats
end

这相当于:

begin
  # iceberg!
rescue StandardError => e
  # lifeboats
end

在少数几个常见的情况下,从Exception中拯救是明智的,其中之一是出于日志(log)记录/报告目的,在这种情况下,您应该立即重新提出例外情况:

begin
  # iceberg?
rescue Exception => e
  # do some logging
  raise # not enough lifeboats ;)
end

Ruby相关问答推荐

如何根据数组键对散列键进行排序?

Ruby 中无法解释的撬动行为

如何解密在 sjcl.js 中使用 ruby​​ 创建的 AES-256-GCM

Ruby注入daisy链?

Ruby $:.unshift File.dirname(__FILE__)

这些 Ruby 命名空间约定之间有什么区别?

在 Ruby 中,如何确定字符串是否不在数组中?

在 RSpec-2.11 中使用隐含的 `subject` 和 `expect`

如何用 Ruby 覆盖 shell 中的打印行?

在 Rails 中,如何向 String 类添加新方法?

错误:Windows 的 SASS 安装

Ruby 将标题发布到 slug

是否可以使用 Ruby 读取文件的修改日期?

野外的好黄瓜例子?

使用 RSpec 判断某物是否是另一个对象的实例

如何在 jekyll markdown 博客中包含视频

如何在 macOS 上卸载 rbenv?

obj.nil?与 obj == nil

让 sidekiq 立即执行作业(job)

带有类名的动态类定义