几年来我一直在使用apache mod_cgi。现在我要转到mod_perl,我发现了一些问题,特别是子程序。到目前为止,我从未使用过my
、our
和local
;CGI脚本工作起来没有问题。在阅读了文档甚至之前在这里发布的一些问题后,我或多或少地了解了my
、our
和local
是如何工作的。我关心的是下一个请求之间将共享什么信息(如果我理解正确的话,这是我在运行mod_perl而不是mod_cgi时必须关心的主要问题)。
- 在标量中使用
our
或仅在标量中不声明任何特殊内容(如my
)之间有什么区别吗?不是都是全球性的吗 - 如果我不将标量声明为private,那么将在下一个请求中共享它?即使在同一服务器中的另一个不同perl脚本请求中
- 如何将子例程内的标量值共享给该子例程外,但不共享同一文件或同一请求外
- 如果我在文件的同一级别或同一子例程中的
if
内的标量中使用my
,然后我创建另一个if
,在那里我使用相同的标量;在两个if
之间共享的标量还是每个if
意味着不同的块?while
和for
呢?它们是以前声明为my
标量的不同块,还是只适用于子例程和文件
mod_perl的工作原理是,根据脚本的名称和路径,将每个perl脚本封装在一个名为handler
的子例程中。这个handler
子例程不是启动一个新的进程来运行每个脚本,而是由许多持久的Perl脚本中的一个调用。
通常,这些知识将有助于理解mod_cgi中的环境变化,但由于您从未将use strict
添加到程序中,并且熟悉声明变量的工作方式,因此您需要进行大量学习!
mod_perl环境有可能导致不明显的安全漏洞,您现在应该在每个脚本上开始use strict
,并声明每一个变量。use Carp
还将帮助您了解错误日志。
用our
声明的变量名是具有相同名称的包变量的词法范围的同义词,可以在不通过包含包名来完全限定名称的情况下使用该包变量。例如,通常用our $var
声明的变量将提供对$main::var
标量的访问(如果之前没有package
声明),而不指定main::
。然而,这些在mod_cgi中以undef
值开始生命的变量现在将保留其先前执行任何给定mod_perl线程时的值,并且为了一致性,始终在声明时初始化它们是最安全的。还要注意的是,由于mod_perl所做的包装,默认包名称不再是main
,因此您不能再使用main::
前缀访问包变量,查找包的实际名称并显式使用它是不明智的,因为它将是一个非常长的名称,并且如果您移动或重命名脚本,它将发生更改。
my
变量是独立于包符号表存在的变量,其生存期通常是封装文件(对于在文件范围内声明的变量)或子例程的运行时间。如果在脚本的文件范围内或完全在一个子例程内声明和使用它们,则它们在mod_perl中是安全的,但如果混合范围并在文件范围内声明my $global
,然后尝试在子例程中使用它,则可能会被刺痛。原因并不简单,但这是由于mod_perl将脚本封装在handler
子例程中,因此您有嵌套的子例程声明。内部子程序将倾向于只采用$global
的第一个实例化,而忽略以后调用handler
创建的任何其他实例化。如果您需要一个全局变量,您应该用our
声明它,并在声明中初始化它,如上所述。
local
变量与our
变量非常相似,因为它形成了包变量的同义词。但是,它会临时保存该变量的当前值,并提供一个新副本以供使用,直到文件或块范围结束。由于它在其范围内自动创建和删除,因此它可以作为mod_perl脚本中my
变量的有用替代方案,特别是在使用指向数据结构的指针(例如CGI
类的实例)的情况下。声明our $cgi = CGI->new
将正确地创建对象,但由于mod_perl的持久性,将把它留在内存中,直到线程的下一次执行删除它,为另一个对象腾出空间。
关于您的问题:
-
如果
use strict
处于应有的位置,则在不声明变量的情况下使用变量会导致编译时错误。否则,它是当前包命名空间中该变量的同义词。 -
变量是包变量或词法变量;没有办法将变量声明为private。词汇变量(用
my
声明)将在每次执行脚本时创建和销毁,除非您通过编写使用在更大范围内声明的变量的子例程创建了一个无效的闭包,此时该变量将是持久的,但不会执行您想要的操作。用our
声明的变量将在对脚本的调用中保留其值,而用local
声明的变量在脚本终止时将被销毁。our
和local
变量都是包变量,对同一变量名的所有引用都指向同一变量。 -
要声明一个在脚本的任何一个调用中处处都可以一致访问的变量,可以使用
local
变量或初始化的our
变量。在文件范围内,local $global
在很大程度上等同于mod_perl脚本的our $global = undef
。如果使用our
变量指向数据结构,请记住在脚本末尾使用undef $global
销毁它。 -
my
变量对于声明它们的块是唯一的,并且在其中是可见的,无论该块是if
、while
或for
内的块,还是仅仅是裸露的{ ... }
块范围内的块。始终将my
变量用于仅在块内使用且不从其他地方访问的临时工作变量。
我希望这能帮助
编辑:这只是关于Perl变量作用域的一般信息。有关mod_perl
的具体问题,请参阅Borodin的帖子。
用my
声明的变量是词法变量。换句话说,它们只存在于当前范围内。默认情况下,您应该使用my
声明所有变量;只有当你特别想要不同的功能时,才做其他事情。
在(几乎)任何语言中,使用词汇范围的变量都是良好代码设计的基本部分。在所有脚本中放入use strict;
和use warnings;
需要遵循此良好做法。
our
是一种声明全局变量的方法;基本结果与使用未声明的全局变量非常相似。然而,它有两个区别:
- 您明确表示希望变量为全局变量。这是一个很好的做法,因为全局变量的使用应该是一个例外。因此,即使使用
use strict;
,也可以通过这种方式创建全局 - 使用
our
声明的变量将可以通过您在当前作用域中的所有包中声明的名称进行访问。相比之下,未声明的变量只能通过当前包中的简单名称访问。除此之外,您只能将其称为$package::variable
有关更多详细信息,请参阅our
的文档。
local
不创建词法变量;相反,它是一种在当前范围内为全局变量提供临时值的方法。它主要与Perl的特殊内置(标点符号)变量一起使用:
{
local $/; #make the record separator undefined in this scope only.
my $file = <FILE>; #read in an entire file at once.
}
您可以简单地对变量始终使用my
,并且只对上面显示的特殊情况使用local
。