我有一組日誌和調試功能,我想跨多個模塊/對象使用。我希望能夠使用命令行開關全局地打開/關閉它們。從Perl模塊導入有條件編譯的函數
下面的代碼是這樣做的,但是,我希望能夠省略軟件包名稱並將所有內容保存在單個文件中。
更具體地說,我想日誌函數的名稱導入到各模塊,讓他們可以在沒有任何包名資格(類似於C++ use namespace;
指令)被調用,我希望能夠啓用/禁用它們全局使用它們的腳本,如下面的示例代碼所示。
另一件事 - 我不認爲我完全理解爲什麼下面的代碼工作。
#! /usr/bin/perl -w
use strict;
use Getopt::Long;
{
package LogFuncs;
use threads;
use Time::HiRes qw(gettimeofday);
# provide tcpdump style time stamp
sub _gf_time {
my ($seconds, $microseconds) = gettimeofday();
my @time = localtime($seconds);
return sprintf("%02d:%02d:%02d.%06ld",
$time[2], $time[1], $time[0], $microseconds);
}
sub logerr;
sub compile {
my %params = @_;
*logerr = $params{do_logging}
? sub {
my $msg = shift;
warn _gf_time() . " Thread " . threads->tid() . ": $msg\n";
}
: sub { };
}
}
{
package FooObj;
sub new {
my $class = shift;
bless {}, $class;
};
sub foo_work {
my $self = shift;
# do some foo work
LogFuncs::logerr($self);
}
}
{
package BarObj;
sub new {
my $class = shift;
my $data = { fooObj => FooObj->new() };
bless $data, $class;
}
sub bar_work {
my $self = shift;
$self->{fooObj}->foo_work();
LogFuncs::logerr($self);
}
}
my $do_logging = 0;
GetOptions(
"do_logging" => \$do_logging,
);
LogFuncs::compile(do_logging => $do_logging);
my $bar = BarObj->new();
LogFuncs::logerr("Created $bar");
$bar->bar_work();
@Eric Strom:但後來我不需要引用包主要將它們拉入我的對象包?和'main :: $ logerr - >(「processing $ _」)一樣,如果$ do_logging> 1;'。整個問題是我試圖簡潔並減少代碼中的打字量和混亂程度。對於不同的日誌/調試級別,我只是有不同的功能,即'loginfo1','loginfo2'等等。我認爲Perl足夠聰明,可以在日誌記錄關閉時優化掉空函數的調用。謝謝,但我認爲你的解決方案不符合我的要求。 – 2010-04-15 06:32:23
@Robert S. Barnes =>不,這不是'my'變量的範圍。詞法不是包的成員,而是作用域級別的成員,因此如果在文件的根作用域中定義了一個詞法變量,它將在同一文件中的每個包下面的程序包/塊中可見。另外,我不認爲perl會優化子呼叫,並且在子呼叫之前計算消息文本的速度可能很慢(例如,如果日誌代碼處於緊密的內部循環中)。通過將檢查外的子檢查移動到調用代碼中,可以防止在調試級別0進行大量不必要的計算。 – 2010-04-15 07:10:55
@Eric Strom:感謝您對可見性的澄清。但是,當我嘗試將日誌函數放在全局範圍內時,它在下面的包中不可見。你是否說我的變量是可見的,而沒有我的聲明的變量不會?關於一方與另一方的表現,唯一真正知道的方法就是測試它。 – 2010-04-15 07:38:10