我一直在研究一个现在没有维护的CPAN模块的分支(据我所知)。在此模块中,他们使用$@
将错误消息传递到堆栈中。换句话说,如果在对子程序的任何调用中出现任何问题,它们会设置$@
,并且在调用之后检查它是否已设置。我之前从未见过这个变量,但我觉得它很有用,所以我开始在代码中使用它。现在我最近读了一些关于它的内容,发现它的目的比这更狭窄。阅读perlvar(以及其他有关此问题的SO问题)对我来说并没有完全回答这个问题,但是,以这种方式使用$@
是否可以?一些"标点符号"我知道的变量肯定不以这种通用方式使用(有些甚至用local
),这是其中一种情况,还是我可以继续这种做法吗?
答案 0 :(得分:4)
$@
。而是在引发异常时自动为您设置。来自perldoc die
:
死LIST
die
引发了异常。在eval
内部,错误消息被填充到$@
中,eval
以未定义的值终止。如果异常在所有封闭eval
之外,则未捕获的异常将LIST打印到STDERR
并以非零值退出。如果您需要使用特定退出代码退出流程,请参阅exit
。
例如,
#!/usr/bin/perl
eval {
print "Hi\n";
die "Something went wrong here";
print "Bye\n";
};
print $@;
打印
Hi
Something went wrong here at ./cr22854919 line 5.
允许使用$@
以这种方式将错误消息传递到堆栈中,作为一种try-catch机制。但是,由于它是一个全局变量,因此应在eval { }
块之后尽快处理它,以确保没有其他代码干扰您对异常的处理。
通常用于错误处理的另一个神奇变量是$!
,其作用类似于C中的errno
。
示例:
my $path = "/tmp/no-such-file";
open F, '<', $path
or print STDERR "$path: $!\n";
输出:
/tmp/no-such-file: No such file or directory
答案 1 :(得分:1)
$@
是Perl中相对“非特殊”的特殊变量。 Perl中的任何内容都没有从$@
读取,并且最后只有eval {}
块写入。这使得它可以相对安全地用于您自己的错误信号目的。
特别是,模块的核心IO::Socket
树使用它来指示构造函数的失败:
use IO::Socket::IP;
my $sock = IO::Socket::IP->new(...) or die "Cannot connect - $@";
更传统的$!
在这里不合适,因为$!
具有包装libc级errno
结构的魔力;意味着它只能设置为整数errno
值,即使它可以读作数字或字符串。因为有时可能会发生与errno
值没有直接关系的失败(例如,在IO::Socket
的情况下,例如多种解析器失败),有时候$!
不适合这种情况。 / p>