在Perl中,有三种主要的变量声明类型:my,our和state。
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # 输出 1,然后 2,然后 3 }
正确使用场景:
my — 如果没有全局访问的理由,几乎总是首选变量声明。our — 用于在模块之间导出变量,当需要共享时。state — 在变量需要在函数调用之间“记住”值的情况下(例如,调用计数器)。使用our声明的变量是否可以在闭包中被捕获?
通常的答案是“可以的,这很方便”,但实际上并非如此。our 变量是对包全局的,闭包并非在创建闭包时绑定它的值,而是通过全局名称进行访问。因此,它的“值”可能会在闭包外部发生变化,并影响所有闭包!
our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # 返回 42,而不是 10
故事
在一个大型日志解析脚本中,变量通过our声明,以便在模块的不同函数中“方便访问”。结果,在一个函数中对这些变量的更改导致另一个函数中出现意外行为,破坏了并行日志处理。
故事
将my用于需要在函数调用之间保存值的变量(例如,递归遍历中的计数器)会导致每次调用时值重置,从而引发遍历逻辑不正确。更换为state解决了这个问题。
故事
在导入模块中不正确使用our(非通过Exporter导出变量)导致在连接两个使用相同变量名的不同模块时名称冲突。最终数据在一个上下文中“跳转”到另一个上下文中。