很多时候,我们学习一门语言,其实就是在学习它的标准库。
Lua 比较小巧,内置的标准库并不多。而且,在 OpenResty 的环境中,Lua 标准库的优先级是很低的。对于同一个功能,我更推荐你优先使用 OpenResty 的 API 来解决,然后是 LuaJIT 的库函数,最后才是标准 Lua 的函数。OpenResty的API > LuaJIT的库函数 > 标准Lua的函数
,这个优先级后面会被反复提及,它不仅关系到是否好用这一点,更会对性能产生非常大的影响。
不过,尽管如此,在实际的项目开发中,我们还是不可避免会用到一些 Lua 库。这里,我挑选了几个比较常用的标准库做下介绍,如果你想要了解更多内容,可以查阅 Lua 的官方文档。
string 库
字符串操作是我们最常用到的,也是坑最多的地方。有一个简单的原则,那就是如果涉及到正则表达式的,请一定要使用 OpenResty 提供的 ngx.re.*
来解决,不要用 Lua 的 string.*
处理。这是因为,Lua 的正则独树一帜,不符合 PCRE 的规范,我相信绝大部分工程师是玩不转的。
其中 string.byte(s [, i [, j ]])
,是比较常用到的一个 string 库函数,它返回字符 s[i]、s[i + 1]、s[i + 2]、······、s[j] 所对应的 ASCII 码。i 的默认值为 1,即第一个字节,j 的默认值为 i。
下面我们来看一段示例代码:
resty -e 'print(string.byte("abc", 1, 3))
print(string.byte("abc", 3)) -- 缺少第三个参数,第三个参数默认与第二个相同,此时为 3
print(string.byte("abc")) -- 缺少第二个和第三个参数,此时这两个参数都默认为 1
'
它的输出为:
979899
99
97
table 库
在 OpenResty 的上下文中,对于 Lua 自带的 table 库,除了 table.concat
、table.sort
等少数几个函数,大部分我都不推荐使用。至于它们的细节,我们留在 LuaJIT 章节中专门来讲。
这里我简单提一下table.concat
。table.concat
一般用在字符串拼接的场景下,比如下面这个例子。它可以避免生成很多无用的字符串。
resty -e 'local a = {"A", "b", "C"}
print(table.concat(a))'
math 库
Lua math 库由一组标准的数学函数构成。数学库的引入,既丰富了 Lua 编程语言的功能,同时也方便了程序的编写。
在 OpenResty 的实际项目中,我们很少用 Lua 去做数学方面的运算,不过其中和随机数相关的 math.random()
和 math.randomseed()
两个函数,倒是比较常用,比如下面的这段代码,它可以在指定的范围内,随机地生成两个数字。
resty -e 'math.randomseed (os.time())
print(math.random())
print(math.random(100))'
虚变量
了解了这些常见的标准库,接下来,我们再来学习一个新的概念——虚变量。
设想这么一个场景,当一个函数返回多个值的时候,有些返回值我们并不需要,这时候,应该怎么接收这些值呢?
不知道你是怎么看待这件事的,起码对我来说,要想法设法给这些用不到的变量,去赋予有意义的名字,着实是一件很折磨人的事情。
还好, Lua 中可以完美地解决这一点。Lua 提供了一个虚变量(dummy variable)的概念, 按照惯例以一个下划线来命名,用来表示丢弃不需要的数值,仅仅起到占位的作用。
下面我们以 string.find
这个标准库函数为例,来看虚变量的用法。这个标准库函数会返回两个值,分别代表开始和结束的下标。
如果我们只需要获取开始的下标,那么很简单,只声明一个变量来接收 string.find
的返回值即可:
resty -e 'local start = string.find("hello", "he")
print(start)'
输出: 1
但如果你只想获取结束的下标,那就必须使用虚变量了:
resty -e 'local _, end_pos = string.find("hello", "he")
print(end_pos)'
输出:2
除了在返回值里使用,虚变量还经常用于循环中,比如下面这个例子:
resty -e 'for _, v in ipairs({4,5,6}) do
print(v)
end'
输出:
4
5
6
出自
温铭 -OpenResty从入门到实战 专栏