• Perl的特殊代码块:BEGIN、CHECK、INIT、END和UNITCHECK


    这是5个特殊的代码块。要理解这几个块,关键在于几个时间点:

    • (1).程序编译期间
    • (2).程序执行期间
    • (3).程序执行结束但还未退出期间

    BEGIN块

    • BEGIN块是在程序编译期间执行的,也就是上面的步骤(1)所在期间
    • 即使程序中出现了语法错误,BEGIN块也会执行
    • 如果出现了多个BEGIN块,则按照FIFO(first in first out)的方式输出,也就是从上到下的顺序

    在BEGIN期间可以做一些程序执行之前的操作,例如事先给某个比较特殊的变量赋值,检查文件是否存在,检查操作系统是否满足要求等等。

    package Foo;
    use strict;
    use warnings;
    BEGIN {
        print "This is the first BEGIN block
    ";
    }
    
    print "The program is running
    ";
    
    BEGIN {
        print "This is the second BEGIN block
    ";
    }
    

    由于BEGIN代码块在编译期间执行,程序普通行的print是在执行期间执行,所以上面的代码结果为:

    This is the first BEGIN block
    This is the second BEGIN block
    The program is running
    

    下面程序出现语法错误,但BEGIN也会执行:

    BEGIN {
        print "This is the first BEGIN block
    ";
    }
    
    print "The program is running
    ";
    
    BEGIN {
        print "This is the second BEGIN block
    ";
    }
    my $x =;
    

    执行结果:

    syntax error at some_program.pl line 8, near "=;"
    Execution of some_program.pl aborted due to compilation errors.
    This is the first BEGIN block
    This is the second BEGIN block
    

    不过上面的error信息不一定会最先输出,因为stdout和stderr是两个独立的文件句柄,无法保证它们之间的顺序。

    实际上,use导入模块时如果导入的是空列表,它等价于在BEGIN中使用require语句:

    use File::Find ();
    # 等价于
    BEGIN {
        require File::Find;
    }
    

    END块

    END块是在程序执行结束,但退出前执行的,也就是上面的步骤(3)所在期间。

    • 当触发了die的时候,它们也会执行
    • 但可以通过信号来忽略END
    • 它们的执行顺序是LIFO(last in first out),即从下往上输出
    • END常用来做清理、善后操作
    END {
        print "This is the first END block
    ";
    }
    
    END {
        print "This is the second END block
    ";
    }
    

    输出结果:注意,先输出second END,再输出first END

    This is the second END block
    This is the first END block
    

    INIT、CHECK 和 UNITCHECK 块

    INIT、CHECK 和 UNITCHECK 块生效于程序编译结束之后、执行之前。所以如果语法错误,它们不会被触发。

    • CHECK在编译结束后立即执行,即上面步骤(1)刚完成之后,输出格式为LIFO
    • INIT紧跟在CHECK之后,也是在步骤(2)之前,输出格式为FIFO
    • UNITCHECK是在perl 5.9.5之后引入的功能。用于解决执行期间require或do或eval导入文件时不触发CHECK和INIT的问题(因为这些语句的导入是在执行期间进行的,而这两个块是在编译期间进行的)。UNITCHECK是在导入的文件刚编译完成之后、执行之前立即执行的
    INIT {
        print "This is the first INIT block
    ";
    }
    CHECK {
        print "This is the first CHECK block
    ";
    }
    INIT {
        print "This is the second INIT block
    ";
    }
    CHECK {
        print "This is the second CHECK block
    ";
    }
    

    输出结果:

    This is the second CHECK block
    This is the first CHECK block
    This is the first INIT block
    This is the second INIT block
    
  • 相关阅读:
    编写测试类实现并发访问固定URL(亲测能用!!!)
    java项目添加log4j打印日志+转换系统时间
    springboot项目没错,但就是报红叉
    我想查看数据库名,输入命令:select name from v$database;为什么会说表和视图不存在
    DRUID连接池的实用 配置详解+使用方法+监控方式(太强大了!!!)
    Druid连接池 属性说明
    springBoot2.2.0+mybatis-xml文件方式+Oracle11g+jsp页面,实现简单的CRUD
    s5-12 RIP
    s5-12 RIP
    s5-13 RIP 为什么会 衰败
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/9780625.html
Copyright © 2020-2023  润新知