评估和死亡
这是处理异常的内置方法,而不依赖于像 Try::Tiny 这样的第三方库。
my $ret;
eval {
$ret = some_function_that_might_die();
1;
} or do {
my $eval_error = $@ || "Zombie error!";
handle_error($eval_error);
};
# use $ret
我们滥用die
具有错误返回值的事实,并且整个代码块的返回值是代码块中最后一个表达式的值:
- 如果
$ret
被成功分配,那么1;
表达式是eval
代码块中发生的最后一件事。因此eval
代码块具有真值,因此or do
块不会运行。 - 如果
some_function_that_might_die()
做了die
,那么在eval
代码块中发生的最后一件事就是die
。因此,eval
代码块具有错误值,并且or do
块确实运行。 - 你必须在
or do
区块做的第一件事是阅读$@
。这个全局变量将保存传递给die
的任何参数。|| "Zombie Error"
后卫很受欢迎,但在一般情况下是不必要的。
这一点很重要,因为有些并非所有代码都通过调用 die 而失败,但无论如何都可以使用相同的结构。考虑一个返回的数据库函数:
- 成功影响的行数
'0 but true'
如果查询成功但没有行受到影响0
如果查询不成功。
在这种情况下,你仍然可以使用相同的习语,但你必须跳过最后的 1;
,这个函数必须是 eval 中的最后一个。像这样的东西:
eval {
my $value = My::Database::retrieve($my_thing); # dies on fail
$value->set_status("Completed");
$value->set_completed_timestamp(time());
$value->update(); # returns false value on fail
} or do { # handles both the die and the 0 return value
my $eval_error = $@ || "Zombie error!";
handle_error($eval_error);
};