Lua 是所有脚本语言中最快、最简洁的,我们爱她的快、她的简洁,但是我们也不得不忍受因为这些快、简洁最后带来的一些弊端,我们来挨个数数 module 有多少“邪恶”的吧。由于 lua_code_cache off 情况下,缓存的代码会伴随请求完结而释放。module 的最大好处缓存这时候是无法发挥的,所以本章的内容都是基于 lua_code_cache on 的情况下。
看下面示例代码:local str = "abcde"print("case 1:", str:sub(1, 2))print("case 2:", str.sub(str, 1, 2))执行结果:case 1: abcase 2: ab冒号操作会带入一个 self 参数,用来代表 自己。而点号操作,只是 内容 的展开。在函数定义时,使用冒号将默认接收一个 self 参数,而使用点号则需要显式传入 self 参数。
Lua 里面的函数必须放在调用的代码之前,下面的代码是一个常见的错误:-- test.lua 文件local i = 100i = add_one(i)function add_one(i) return i + 1end我们将得到如下错误:# luajit test.lualuajit: test.lua:2: attempt to call global 'add_one' (a nil value)stack traceback: test.
旧式的模块定义方式是通过 module("filename"[,package.seeall])* 来显式声明一个包,现在官方不推荐再使用这种方式。这种方式将会返回一个由 filename 模块函数组成的 table,并且还会定义一个包含该 table 的全局变量。module("filename", package.seeall) 这种写法是不提倡的,官方给出了两点原因:package.seeall 这种方式破坏了模块的高内聚,原本引入 "
当一个方法返回多个值时,有些返回值有时候用不到,要是声明很多变量来一一接收,显然不太合适(不是不能)。Lua 提供了一个虚变量(dummy variable),以单个下划线(“_”)来命名,用它来丢弃不需要的数值,仅仅起到占位的作用。看一段示例代码:-- string.
在 OpenResty 中,同时存在两套正则表达式规范:Lua 语言的规范和 ngx.re.* 的规范,即使您对 Lua 语言中的规范非常熟悉,我们仍不建议使用 Lua 中的正则表达式。一是因为 Lua 中正则表达式的性能并不如 ngx.re.* 中的正则表达式优秀;二是 Lua 中的正则表达式并不符合 POSIX 规范,而 ngx.re.* 中实现的是标准的 POSIX 规范,后者明显更具备通用性。
大家在使用 Lua 的时候,一定会遇到不少和 nil 有关的坑吧。有时候不小心引用了一个没有赋值的变量,这时它的值默认为 nil。如果对一个 nil 进行索引的话,会导致异常。如下:local person = {name = "Bob", sex = "M"}-- do somethingperson = nil-- do somethingprint(person.
table.getn(t) 等价于 #t 但计算的是数组元素,不包括 hash 键值。而且数组是以第一个 nil 元素来判断数组结束。# 只计算 array 的元素个数,它实际上调用了对象的 metatable 的 __len 函数。对于有 __len 方法的函数返回函数返回值,不然就返回数组成员数目。
Lua 的设计有一点很奇怪,在一个 block 中的变量,如果之前没有定义过,那么认为它是一个全局变量,而不是这个 block 的局部变量。这一点和别的语言不同。容易造成不小心覆盖了全局同名变量的错误。
类在 Lua 中,我们可以使用表和函数实现面向对象。将函数和相关的数据放置于同一个表中就形成了一个对象。请看文件名为 account.lua 的源码:local _M = {}local mt = { __index = _M }function _M.deposit (self, v) self.balance = self.balance + vendfunction _M.withdraw (self, v) if self.balance > v then self.balance = self.
在 Lua 5.1 语言中,元表 (metatable) 的表现行为类似于 C++ 语言中的操作符重载,例如我们可以重载 "__add" 元方法 (metamethod),来计算两个 Lua 数组的并集;或者重载 "__index" 方法,来定义我们自己的 Hash 函数。Lua 提供了两个十分重要的用来处理元表的方法,如下:setmetatable(table, metatable):此方法用于为一个表设置元表。
Lua I/O 库提供两种不同的方式处理文件:隐式文件描述,显式文件描述。这些文件 I/O 操作,在 OpenResty 的上下文中对事件循环是会产生阻塞效应。OpenResty 比较擅长的是高并发网络处理,在这个环境中,任何文件的操作,都将阻塞其他并行执行的请求。实际中的应用,在 OpenResty 项目中应尽可能让网络处理部分、文件 I/0 操作部分相互独立,不要揉和在一起。
Lua 数学库由一组标准的数学函数构成。数学库的引入丰富了 Lua 编程语言的功能,同时也方便了程序的编写。常用数学函数见下表:函数名函数功能math.rad(x)角度x转换成弧度math.deg(x)弧度x转换成角度math.max(x, ...)返回参数中值最大的那个数,参数必须是number型math.min(x, ...)返回参数中值最小的那个数,参数必须是number型math.
在 Lua 中,函数 time、date 和 difftime 提供了所有的日期和时间功能。在 OpenResty 的世界里,不推荐使用这里的标准时间函数,因为这些函数通常会引发不止一个昂贵的系统调用,同时无法为 LuaJIT JIT 编译,对性能造成较大影响。推荐使用 ngx_lua 模块提供的带缓存的时间接口,如 ngx.today, ngx.time, ngx.utctime,ngx.localtime, ngx.now, ngx.http_time,以及 ngx.
table 库是由一些辅助函数构成的,这些函数将 table 作为数组来操作。下标从 1 开始在 Lua 中,数组下标从 1 开始计数。官方解释:Lua lists have a base index of 1 because it was thought to be most friendly for non-programmers, as it makes indices correspond to ordinal element positions.
Lua 字符串库包含很多强大的字符操作函数。字符串库中的所有函数都导出在模块 string 中。在 Lua 5.1 中,它还将这些函数导出作为 string 类型的方法。这样假设要返回一个字符串转的大写形式,可以写成 ans = string.upper(s) , 也能写成 ans = s:upper()。为了避免与之前版本不兼容,此处使用前者。Lua 字符串总是由字节构成的。
从 Lua 5.1 语言添加了对模块和包的支持。一个 Lua 模块的数据结构是用一个 Lua 值(通常是一个 Lua 表或者 Lua 函数)。一个 Lua 模块代码就是一个会返回这个 Lua 值的代码块。可以使用内建函数 require() 来加载和缓存模块。简单的说,一个代码模块就是一个程序库,可以通过 require 来加载。
调用回调函数,并把一个数组参数作为回调函数的参数。local args = {...} or {}method_name(unpack(args, 1, table.maxn(args)))使用场景如果你的实参 table 中确定没有 nil 空洞,则可以简化为method_name(unpack(args))你要调用的函数参数是未知的;函数的实际参数的类型和数目也都是未知的。伪代码add_task(end_time, callback, params)if os.time() >
Lua 具有一项与众不同的特性,允许函数返回多个值。Lua 的库函数中,有一些就是返回多个值。示例代码:使用库函数 string.find,在源字符串中查找目标字符串,若查找成功,则返回目标字符串在源字符串中的起始位置和结束位置的下标。local s, e = string.find("hello world", "llo")print(s, e) -->output 3 5返回多个值时,值之间用“,”隔开。
关注时代Java