Lua进阶语法

更多详细代码案例在GitHub,意见和问题请在公众号留言
https://github.com/kuweiguge/OpenResty-Lua-Labs

模块

Lua支持模块,你可以将一组相关的函数和变量组织在一个模块中。模块可以被其他Lua脚本引用。

-- mathlib.lua
local mathlib = {}

function mathlib.add(x, y)
    return x + y
end

return mathlib

-- main.lua
local mathlib = require("mathlib")
print(mathlib.add(10, 20))  -- 30

元表和元方法

Lua提供了元表和元方法的概念,允许你定义和修改值的行为。例如,你可以使用元表来定义如何比较两个表,或者定义如何将两个表相加。

local set1 = {10, 20, 30} --集合set1
local set2 = {20, 30, 40} --集合set2
local mt = {}  -- 空的元表

-- 定义元方法(计算两个集合的并集)
-- 遍历集合 a 和 b,将集合中的每个元素添加到result集合中。由于result集合是以集合元素为键的表,所以重复的元素会被覆盖,从而实现了并集的效果。
function mt.__add(a, b)
    local result = {}
    for _, v in pairs(a) do result[v] = true end
    for _, v in pairs(b) do result[v] = true end
    return result
end

-- 使用 setmetatable 函数将元表 mt 设置为 set1 和 set2 的元表。
-- 这样,当对这两个集合执行加法操作时,Lua 会调用元表中的 __add 方法。
setmetatable(set1, mt)
setmetatable(set2, mt)

local set3 = set1 + set2
for k in pairs(set3) do
    ngx.say(k)
end
-- 需要注意的是,这段代码中的并集操作只适用于元素为数字或字符串的集合,如果集合中的元素是表或其他复杂类型,可能需要更复杂的处理方式。

setmetatable 是 Lua 语言中的一个函数,用于设置或修改表的元表。元表是一种特殊的表,它可以改变表的行为,例如进行算术运算、比较运算、连接操作等。
在这段代码中,setmetatable(set1, mt)setmetatable(set2, mt)mt 设置为 set1set2 的元表。这样,当对 set1set2 执行加法操作时,Lua 会调用元表中的 __add 方法。
__add 是元表的一个特殊字段,用于定义加法操作。在这个例子中,__add 方法被定义为计算两个集合的并集。
所以,setmetatable 函数在这里的作用是,让 set1set2 在执行加法操作时,按照我们自定义的方式(即计算并集)来执行。

Lua 中的元方法有很多,以下是一些常见的元方法及其作用:

  1. __add(a, b): 对两个表进行加法操作时的行为。
  2. __sub(a, b): 对两个表进行减法操作时的行为。
  3. __mul(a, b): 对两个表进行乘法操作时的行为。
  4. __div(a, b): 对两个表进行除法操作时的行为。
  5. __mod(a, b): 对两个表进行取模操作时的行为。
  6. __pow(a, b): 对两个表进行幂运算操作时的行为。
  7. __unm(a): 对表进行取反操作时的行为。
  8. __concat(a, b): 对两个表进行连接操作时的行为。
  9. __len(a): 获取表长度时的行为。
  10. __eq(a, b): 对两个表进行等于操作时的行为。
  11. __lt(a, b): 对两个表进行小于操作时的行为。
  12. __le(a, b): 对两个表进行小于等于操作时的行为。
  13. __index(a, b): 访问表中不存在的字段时的行为。
  14. __newindex(a, b, c): 对表中不存在的字段进行赋值操作时的行为。
  15. __call(a, ...): 当表被当作函数调用时的行为。
  16. __tostring(a): 当表被当作字符串使用时的行为。
  17. __metatable: 用于保护元表,当设置为一个表时,将禁止对原表更改元表和获取元表。

这些元方法可以让你自定义表的行为,使其更符合你的需求。

协程

Lua支持协程,也称为轻量级线程。协程是一种可以暂停和恢复执行的计算机程序组件,非常适合用来处理异步任务。

local co = coroutine.create(function ()
    for i = 1, 10 do
        print(i)
        coroutine.yield()
    end
end)

coroutine.resume(co)  -- 1
coroutine.resume(co)  -- 2

首先,使用 coroutine.create 函数创建了一个协程 co。这个协程的主体是一个匿名函数,这个函数中有一个循环,循环体中首先输出一个数字,然后调用 coroutine.yield 函数让出 CPU 控制权,使协程暂停执行。
然后,使用 coroutine.resume 函数恢复协程的执行。每次调用 coroutine.resume,协程会从上次暂停的地方继续执行,直到遇到下一个 coroutine.yield 调用或者到达函数末尾。在这个例子中,每次恢复协程,都会输出一个数字,然后协程再次暂停。
这段代码中,coroutine.resume(co) 被调用了两次,所以当访问 /lesson9 路径时,会输出两个数字:1 和 2。
协程是一种可以暂停和恢复执行的轻量级线程,它可以用来实现非阻塞 IO、协作式多任务等功能。在 Nginx + Lua 的环境中,协程是实现高并发、高性能网络服务的关键技术。

文件I/O

Lua提供了一套文件I/O函数,你可以使用这些函数来读写文件。

-- 写文件
local file = io.open("test.txt", "w")
file:write("Hello, OpenResty")
file:close()

-- 读文件
local file = io.open("test.txt", "r")
local content = file:read("*a")
file:close()
print(content)  -- Hello, OpenResty

Lua和C的交互

Lua提供了一套C API,允许你在C程序中调用Lua代码,也可以在Lua代码中调用C函数。这使得Lua可以很好地和C程序进行交互。

// C程序
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main() {
    lua_State *L = luaL_newstate();  // 创建Lua状态机
    luaL_openlibs(L);  // 打开Lua标准库

    luaL_dofile(L, "test.lua");  // 执行Lua脚本

    lua_close(L);  // 关闭Lua状态机
    return 0;
}
-- test.lua
print("Hello, OpenResty")

Lua中的面向对象编程

虽然Lua本身并不直接支持面向对象编程,但是你可以使用表和元表来模拟类和对象。

local Person = {}
Person.__index = Person

function Person.new(name, age)
    local self = setmetatable({}, Person)
    self.name = name
    self.age = age
    return self
end

function Person:sayHello()
    print("Hello, my name is " .. self.name)
end

local p = Person.new("OpenResty", 10)
p:sayHello()  -- Hello, my name is OpenResty

Lua中的函数式编程

Lua支持一等函数和闭包,这使得你可以在Lua中进行函数式编程。

function add(x)
    return function(y)
        return x + y
    end
end

local add10 = add(10)
print(add10(20))  -- 30
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容