3.1 Lua入门与规范
Lua是一门小巧的脚本语言,于1993年在巴西里约热内卢天主教大学诞生。从发布至今,Lua语言几经沉浮。下面我们一起走进Lua语言的世界。在本节中,笔者会带领读者一起了解Lua语言的基础知识、安装流程、解释器原理及一些常用的使用规范。
3.1.1 基础知识
Lua根据标准C编写而成,几乎在所有操作系统和平台上都可以编译、运行。Lua虽小,但五脏俱全。其源码包大小仅有200KB,却拥有一组精简且强大的特性,以及易使用的C API,这使得它非常容易嵌入其他应用程序,从而提供灵活、丰富的扩展和定制功能。然而,Lua语言并没有提供强大的功能库,所以它无法形成完整的技术生态。当然,这是由它的定位所决定的。因此,Lua语言不太适合用来独立开发应用程序。
除此之外,Lua还有一个同期进行的LuaJIT项目,即Just-In-Time,也就是运行时编译器。LuaJIT的语法和标准Lua的语法类似,但是其运行速度比标准Lua快数十倍,可以说是Lua的一个高效率版本。
Lua因为其语言特点,常用于游戏脚本引擎,如《魔兽世界》《愤怒的小鸟》。Lua与Nginx生态环境也结合得非常紧密。Lua语言大量用于OpenResty和Kong插件中。总体而言,Lua语言是C\C++的“王牌搭档”。C\C++应用程序与Lua语言结合完美地平衡了性能和灵活性,这也正是Kong网关能够提供高性能和高度定制化插件的基础。
注意
Lua是作为一门胶水语言出现的。区别于C、Java或者Python等生态语言,它没有自己独立的环境,必须依附在宿主语言环境中才能起作用。所以说从一开始,Lua就非常明确自己的定位:它不想自己做大,而是想做得足够精简、小巧,嵌入宿主语言,以提供一些动态特性。除Lua之外,常用的胶水语言还有Shell脚本、TCL语言等。
3.1.2 安装指南
下面我们一起来安装Lua。与之前几章类似,笔者提供三种不同场景下的安装方法。读者根据自己开发环境选择安装。
1.在Mac环境中安装Lua
在Mac环境中,我们还是选用Homebrew工具安装。安装过程如下所示:
# 安装Homebrew,如果已经安装请忽略 $ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" # 安装Lua $ brew install lua # 验证是否安装成功 $ lua -v Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
当系统提示Lua 5.3.5 Copyright(C)1994-2018 Lua.org,PUC-Rio信息,表示Lua环境已经安装成功。
2.在Linux环境中安装Lua
大多数Linux系统已经预装Lua程序,一般情况下可以直接使用,但建议读者检查一下预装Lua的版本,以防中途因版本问题而引发意外。下面是在Linux环境中重新安装Lua的方法。
$ wget -P /root https://www.lua.org/ftp/lua-5.3.5.tar.gz $ cd /root && tar xf lua-5.3.5.tar.gz && cd lua-5.3.5 $ make all linux $ rm -rf /usr/local/bin/lua $ rm -rf /usr/bin/lua $ ln -s /root/lua-5.3.5/src/lua /usr/bin/lua $ ln -s /root/lua-5.3.5/src/lua /usr/local/bin/lua $ lua -v Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
3.在Docker环境中安装Lua
使用Docker容器安装Lua的方法:
$ docker pull nickblah/lua:5.3.5 $ docker run -it nickblah/lua:5.3.5 /bin/bash $ lua -v Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
安装完毕后,我们简单运行一个Hello World程序。
·用户可以在控制台先输入Lua脚本,直接进入交互模式:
> print("Hello World") Hello World
·用户也可以选择非交互模式运行:
$ echo "print('Hello World')" > helloworld.lua $ lua helloworld.lua Hello World
3.1.3 解释器
解释器(Interpreter),又称为直译器,能够把高级编程语言转译并运行。它像一个中间人,每次程序运行时都要先转成另一种语言再运行。
在3.1.2节中,用户能够如此便捷地完成Hello World示例就依赖于解释器。解释器显著地提升了程序开发效率,并简化了调试步骤。在交互模式下,用户可以即时获得程序的执行结果。这种所见即所得的交互流程使得编码过程人性化、透明,也大大降低了前期编码的试错成本。
解释器也有弱势,比如相较于二进制文件或者字节码,运行速度比较慢。考量一个编程语言是否足够优秀,性能是极其重要的。Lua语言针对此问题,给出了自己的解决方案,即LuaJIT。这里展示一个简单的示例比较两者的执行效率。代码清单3-1为Lua解释器示例,代码清单3-2为LuaJIT解释器示例,代码清单3-3为两者运行时间的对比。
程序清单3-1 Lua的解释器示例
1 #!/usr/local/bin/lua 2 local i = 0 3 while 1 do 4 i = i+1 5 ifi > 10000000 then 6 print(i) 7 break 8 end 9 end
程序清单3-2 LuaJIT的解释器示例
1 #!/usr/local/bin/luajit 2 local i = 0 3 while 1 do 4 i = i+1 5 if i > 10000000 then 6 print(i) 7 break 8 end 9 end
程序清单3-3 运行时间对比
$ time ./lua.lua 10000001 ./lua.lua 0.16s user 0.00s system 96% cpu 0.166 total $ time ./luajit.lua 10000001 ./luajit.lua 0.01s user 0.00s system 88% cpu 0.015 total
可以发现,LuaJIT解释器的执行效率为Lua解释器执行效率的10倍以上。LuaJIT还有很多其他性能优化技巧。感兴趣的读者可以自行查阅资料学习,这对我们今后进行Lua脚本开发有非常大的帮助,也是提升性能指标的关键点。
3.1.4 语法规范
大多数编程语言保留了关键字,Lua语言也不例外。这些关键字不可以用作标识符。相较于C语言,Lua语言保留的关键字比较少(仅22个),如表3-1所示。这也间接体现了Lua相对简洁的语言特征。
表3-1 Lua语言保留的关键字
标识符是由非数字开头的任意字母、下划线和数字构成的字符串。Lua语言是区分大小写的。推荐使用驼峰命名法或下划线命名法定义标识符。
注意
标识符命名风格
驼峰命名法:正如它的名称CamelCase一样,混合使用大小写字母,首字母小写,常用于面向对象语言命名。
下划线命名法:名称中的每一个逻辑端点都使用下划线分隔,常用于类C语言环境。
Lua语言的一个编译单元被称为一个代码块。从句法构成上讲,一个代码块就是一个语句块。代码块内可以定义局部变量,也可以接收参数,返回若干值,如代码清单3-4所示。
程序清单3-4 Lua语言代码块示例
> do >> local function foo(...) -- 定义一个局部函数 >> for i = 1, select('#', ...) do -- 获取参数总数 >> local arg = select(i, ...); -- 局部变量读取参数 >> print("arg", arg); >> end >> end >> foo(1, 2, 3, 4); >> end arg 1 arg 2 arg 3 arg 4
上述例子遵循着词法作用域规则。局部变量可以在它的作用范围内被定义的函数自由使用。当一个局部变量被内层的函数使用的时候,它被内层函数称作上值或者外部局部变量。每次执行到一个local语句都会定义一个新的局部变量。