如果Perl代码出现问题,最佳做法是什么?

Geo*_*Geo 4 perl exception-handling

可能重复:
如何在Perl中干净地处理错误检查?
Perl中的异常有什么问题?

我看到的代码如下:

do_something($param) || warn "something went wrong\n";
Run Code Online (Sandbox Code Playgroud)

我也看到了这样的代码:

eval {
  do_something_else($param);
};
if($@) {
  warn "something went wrong\n";
}
Run Code Online (Sandbox Code Playgroud)

我应该在所有子程序中使用eval/die吗?我应该根据子程序返回的内容编写所有代码吗?是不是eval代码(一遍又一遍)会让我慢下来?

hob*_*bbs 13

eval不是字符串eval,所以不,它不慢.绝对推荐使用它.

虽然它的工作方式有一些令人烦恼的微妙之处(主要$@是全局变量这一事实令人讨厌的副作用),所以考虑使用Try :: Tiny而不是记住你需要eval防御性使用的所有小技巧.


Sin*_*nür 6

do_something($param) || warn "something went wrong\n";
Run Code Online (Sandbox Code Playgroud)

在这种情况下,do_something如果出现问题,预计会返回错误代码.要么它不能死,要么它死了,这是一个非常不寻常的情况.

eval {
  do_something_else($param);
};
if($@) {
  warn "something went wrong\n";
}
Run Code Online (Sandbox Code Playgroud)

在这里,假设do_something_else是通过抛出异常来传达出错的唯一机制.

如果do_something_else在真正异常情况下抛出异常并在其他一些情况下返回错误值,则还应检查其返回值.

使用eval的块形式不会在运行时引起额外的编译,因此没有严重的性能缺陷:

在第二种形式中,在块内的代码被解析一次-在同一时间环绕代码eval本身被解析-和当前Perl程序的上下文内执行.此表单通常用于比第一个表单更有效地捕获异常(见下文),同时还提供BLOCK在编译时检查代码的好处.


jro*_*way 6

模块warn非常烦人.成功或失败.不要在终端上打印东西然后继续运行; 我的程序无法根据您打印的某些消息采取措施.如果程序可以继续运行,只有在明确告知它没有问题时才打印一条消息.如果程序无法继续运行,die.这就是它的用途.

当出现问题时总是抛出异常.如果您可以解决问题,请修复它.如果你无法解决问题,请不要尝试; 抛出异常并让调用者处理它.(如果你不能处理你所呼叫的异常,请不要.)

基本上,许多程序出错的原因是因为他们试图修复他们无法解决的错误.在问题的第一个迹象下干净地死亡的程序易于调试和修复.一个在困惑时继续运行的程序只会破坏数据并使每个人烦恼.所以不要这样做.尽快死去.


Eth*_*her 5

你的两个例子完全不同.第一个检查错误的返回值,并采取一些响应操作.第二个检查被叫代码的实际死亡.

您必须自己决定哪种行为适合每种情况.我建议在大多数情况下简单地返回false.die如果您遇到严重到无法继续的错误(或者没有任何意义继续下去,那么您应该只明确说明,但即便如此,您仍然可以返回false).

包装块eval {}与包装任意代码不是一回事eval "".在前一种情况下,代码仍然在编译时解析,并且您不会产生任何额外的开销.您将简单地捕获该代码的任何死亡(但您不会有任何关于出现问题或代码有多远的指示,除了您留下的值$@).在后一种情况下,Perl解释器将代码视为一个简单的字符串,直到它被实际评估为止,因此在调用解释器时会有一定的成本(并且您将失去对代码的所有编译时检查).

顺便提一下,您调用eval和检查值的$@方式不是推荐的形式; 有关Perl中异常陷阱和技术的广泛讨论,请参阅此讨论.