Perl 使用Try::Tiny还是Eval?
哪个更安全、更好、更清洁、更推荐使用 我用过:Perl 使用Try::Tiny还是Eval?,perl,Perl,哪个更安全、更好、更清洁、更推荐使用 我用过: sub insert_exec { my ($self, $c, $args) = @_; my ($params, $table, $model) = $self->_init({context => $c, args => $args}); eval { $model->insert($table, $params); }; if ($@) { return $c->sh
sub insert_exec {
my ($self, $c, $args) = @_;
my ($params, $table, $model) = $self->_init({context => $c, args => $args});
eval { $model->insert($table, $params);
};
if ($@) { return $c->show_error($@); } ## error
$c->redirect("/index");
}
但是对于这种情况(参见错误部分),我被告知使用Try::Tiny更好
我的问题是:您将如何编写此代码?为什么选择这种方式?不使用
Try::Tiny
可以为您节省额外的依赖性
使用它可以让您在不了解Perl习惯用法的情况下编写可以理解的代码(用业界更常见的术语代替它们)
你需要决定哪些对你更有价值,因为很难客观地衡量它们的相对价值。更新 多亏了一位匿名用户,我才能够纠正我答案中的一个错误。
catch
块中的return
没有达到预期效果,因为它只从catch
子例程返回
如果没有异常,try
返回try
块的值,否则返回catch
块的值。因此,如果插入成功,此版本将正确执行并返回$c->redirect(“/index”)
,否则它将调用并返回$c->show\u error($)
的值
这一点非常重要,因为在一般情况下,使用
eval
处理错误确实非常困难。模块的文档说明了这一点
此模块提供了简单的try/catch/finally语句,旨在最大限度地减少eval块的常见错误,而不是其他错误
本模块的主要重点是为那些。。。他们仍然希望在每次没有5行样板的情况下编写正确的评估块
您的代码如下所示
use Try::Tiny;
sub insert_exec {
my ($self, $c, $args) = @_;
my ($params, $table, $model) = $self->_init({context => $c, args => $args});
try {
$model->insert($table, $params);
}
catch {
return $c->show_error($_);
};
$c->redirect("/index");
}
我希望你会同意,这样更好
有两点值得注意:
和try
是被编码为类似于语言单词的子程序。这意味着在最后一个右大括号后面必须加一个分号catch
- 出于同样的原因,
或try
块中的catch
将无法按预期工作,只需退出块,返回到父子例程。见我的更新上面return
- 在
块中,catch
具有$@
之前的原始值。该错误产生的值位于try
$\uu
$@
发出错误信号,而只是将其用作错误消息的来源,因此我将其写成:
my $success = eval { $model->insert($table, $params) };
unless ($success) {
return $c->show_error($@);
}
如果您评估的内容在成功时可能不会返回真实值,那么:
my $success = eval { $model->insert($table, $params); 1 };
当事情变得比这更复杂时,我可能会使用Try::Tiny,例如,函数返回一个您想要保存的值,但可能不是真值(或者甚至可能没有定义),并且您想要捕获异常。如果匿名用户没有足够的信誉来发布评论试图编辑我的答案,那就更好了,添加此文本。这是一个非常好的观点,我已经做了适当的更新。使用
Try::Tiny
时,结构更好,但与原始帖子有很大不同。在编写时,try和catch块都是子例程,因此catch中的返回仅从匿名sub返回,而不是从insert\u exec
返回。这意味着在异常情况下也会执行重定向。这是Try::Tiny
的常见陷阱。
my $success = eval { $model->insert($table, $params); 1 };