现代Perl编写异常类最佳实践:Throwable系列模块使用疑问
Throwable::Factory 全局异常类实现方案
核心实现逻辑
Throwable::Factory 生成的异常类默认绑定在当前调用栈的命名空间下,只要在项目公共启动入口完成定义+导出,即可实现全局调用,不需要感知内部生成的不透明类名。
步骤1:公共入口预定义异常
在项目统一加载的公共模块(如通用工具包、启动脚本)中完成异常类定义,同时通过Exporter导出到全局:
package MyApp::Exception; use strict; use warnings; # 预定义所有项目需要的异常类型 use Throwable::Factory GeneralError => undef, ParamInvalid => ['-ParamInvalid', fields => [qw/param expected actual/]], DbError => ['-DbError', fields => [qw/dsn sql error/]], NetworkError => ['-NetworkError', fields => [qw/endpoint status/]]; # 导出所有异常构造函数 use parent 'Exporter'; our @EXPORT = qw(GeneralError ParamInvalid DbError NetworkError); 1;
步骤2:全局调用
所有业务代码只要引入上述公共模块,即可直接抛出、捕获异常,用法和Exception::Class完全一致:
# 业务代码引入公共异常模块 use MyApp::Exception; use Try::Tiny; sub query_db { my ($sql) = @_; my $dbh = get_dbh() or DbError->throw(dsn => $dsn, error => '连接失败'); # ... 执行查询逻辑 } try { query_db('select * from test'); } catch { # 异常类型判断 if ($_->isa('DbError')) { warn "数据库错误: " . $_->error; } elsif ($_->isa('ParamInvalid')) { warn "参数错误: " . $_->param . " 需为 " . $_->expected; } else { $_->throw; } };
常见疑问说明
- 你观察到的「不透明类名」是
Throwable::Factory内部自动生成的子类标识,业务层不需要感知,通过导出的异常名称调用throw、属性访问、类型判断的逻辑都可以正常执行。 - 如果不需要自定义字段,可以直接不传
fields参数,异常默认自带message、previous_exception等Throwable标准属性。
内容的提问来源于stack exchange,提问作者Dave Baird
相关产品推荐
相关产品推荐

