淘先锋技术网

首页 1 2 3 4 5 6 7

以下代码都经过测试可以运行,可以使用下面的lua在线运行查看效果,建议在Linux上搭建Lua运行环境(在官网下载源代码,编译生成一个可执行程序即可)。

Lua在线运行测试https://www.bejson.com/runcode/lua/
Lua源码下载地址http://www.lua.org/ftp/

1、if … else …

下面讲解lua变量声明以及条件判断语句

local a = 0				-- 局部变量,number类型 
b = false				-- 全局变量,bool类型 
c = "Hello"				-- string类型 
d, e, f = 0, 1.1		-- d=0,e=1.1,f=nil
g = 1 .. 2				-- g=12, ..会拼接前后的字符串

if a == 0 and b ~= 0 then       -- lua中false不等于0
    print("1") 
elseif c >= 0 or not d then 
    print("2") 
else 
    print("3") 
end

输出结果:1

2、函数

函数大致分为:局部函数,全局函数和成员函数。函数前加local就是局部函数,只能在本文件中被调用;不加local就是全局函数,可以在其他文件调用该函数;成员函数是定义在table里的函数,需要通过table调用。

local function hello()           -- 局部函数,只允许在本文件内调用
    print("Hello world")
end
hello()                          -- 调用函数

输出结果:
Hello world

function average(...)            -- 全局函数,...表示可变参数
   result = 0
   local arg={...}              -- arg为一个表,局部变量,里面存放的是入参
   for i, var in ipairs(arg) do
       result = result + var    -- 入参累加
   end
   print("形参个数:" .. #arg .. " 个")
   return result/#arg
end

print("平均值为:"..average(10,5,3,4,5,6)) -- 调用求平均值函数average()

输出结果:
形参个数:6 个
平均值为:5.5

People = {age = 20}               -- 声明一个类(table)

function People.sayHi(self, name) -- 类的成员函数
    print(name, self.age)
end

People.sayHi(People, "Zhangsan")  -- 直接调用类的成员函数
People:sayHi("Lisi")              -- 将People自身作为实参传入函数,效果同上

输出结果:
Zhangsan 20
Lisi 20

3、table和for循环

table可以看作是C++里的类,里面可以放变量也可以放函数,可以在任意时候往table里增加变量或函数。

People = {hello="Hello lua", world="World"}   -- 初始化table
People.num = 100                              -- 添加元素并赋值
People["name"] = "ZhangSan"                   -- 添加元素并赋值

print(People.num)                             -- 打印num元素的值
print(People["world"])                        -- 打印world元素的值

for key, var in pairs(People) do              -- 遍历数组
    print(key, var)                           -- 打印索引和值,索引从1开始
end

输出结果:
100
World
num 100
name ZhangSan
world World
hello Hello lua

4、面向对象

lua不支持原生的面向对象和多态,但可以通过一些方法事项。以下两段代码需要放在两个文件里:module.lua和test.lua。module可以看作一个类的封装,运行时只调用test.lua。

-- module.lua文件,文件名就是module名
module = {}                        -- 定义一个名为module的模块
module.publiclVar = "公共成员变量"  -- 类成员变量
local privateVar =  "私有成员变量"  -- 局部变量,只能本文件访问

function module.publicFun()        -- public公共函数,可以在外部访问
    io.write("这是一个公有函数!\n")  -- 等同于print() 
end 

local function privateFun()        -- private私有函数,只能在本文件内访问
    print("这是一个私有函数!")
end

return module
-- test.lua文件
require("module")         -- 执行require 后会返回一个由模块常量或函数组成的table,并且还会定义一个包含该table的全局变量。
print(module.publiclVar)  -- 访问module里的成员变量publiclVar,require()函数已经声明了module,可以直接访问 
module.publicFun()        -- 调用module里的成员函数publicFun(),如果调用私有函数privateFun()就会报错

输出结果:(调用test.lua)
公共成员变量
这是一个公有函数!

5、继承和派生

同样,lua也不支持原生的多态,但可以自己实现new函数达到相同的效果。父类在new方法里将所有属性和方法都拷贝给子类,子类在new方法里调用父类的new函数获取父类所有属性和方法,然后再增加自己特有的属性和方法,以此来实现多态,示例代码如下:

Father = {name = "Zhangsan", age = 50}  -- 父类成员变量声明和初始化
Father.hello = function()               -- 父类成员函数
    print("Hello world!")
end

function Father.new(iName) -- 父类new方法
    local ins = {}
    for key, var in pairs(Father) do
        ins[key] = var    -- 将父类所有方法和属性都拷贝给子类
    end
    ins.name = iName
    return ins	-- 返回实例化的父类对象,子类负责接受
end

Son = {}  -- 子类
function Son.new()                 -- 子类new方法
    local ins = Father.new("Lisi") -- 继承父类的所有属性和方法
    ins.sports = "Basketball"      -- 添加子类特有属性或方法
    return ins                     -- 返回实例化的子类对象
end

-- 开始测试
child = Son.new()    -- 实例化子类
child.hello()        -- 调用父类成员函数
print(child.sports)  -- 访问子类属性或方法

输出结果:
Hello world!
Basketball

6、编程技巧

使用goto语句模拟continue

for key, var in pairs(People) do    -- 遍历数组
    if key == 0 then
    	goto continue
    end
    print(key, val)
    ::continue::
end

7、OpenResty常用命令

OpenResty函数库请参考:https://www.kancloud.cn/qq13867685/openresty-api-cn/159139

ngx.var.VAR_NAME                -- 读写 Nginx 变量值
ngx.log(log_level, ...)         -- 将参数拼接起来,按照设定的日志级别记入
ngx.ctx                         -- 请求lua上下文
ngx.header[HEADER]              -- 修改、添加、或清除当前请求待发送的 HEADER 响应头信息。

ngx.shared.DICT                 -- 获取共享内存名为 DICT 的 lua 字段
ngx.shared.DICT:get(key)        -- 从 ngx.shared.DICT 字典中获取名为 key 的键值
ngx.shared.DICT:set(key, value) -- 无条件在基于共享内存的字典 ngx.shared.DICT 中设置一个 key-value (键-值)对 

ngx.req.get_headers()           -- 获取请求头信息,函数返回一个table
ngx.req.get_uri_args()          -- 获取当前请求的所有URL 查询参数
ngx.req.set_uri_args(args)      -- 用 args 参数重写当前请求的 URI 请求参数
ngx.req.set_uri(uri, jump?)     -- 用 uri 参数重写当前请求,jump为 true 时,此函数将不会返回;为 false 时只有当前请求的 URI 被改写
ngx.req.get_body_data()         -- 取回内存中的请求体数据。本函数返回 Lua 字符串而不是包含解析过参数的 Lua table 
ngx.req.get_method()            -- 获取当前请求的HTTP请求方法名称
ngx.req.read_body()             -- 同步读取客户端请求体,不阻塞 Nginx 事件循环

ngx.status                      -- 读写当前请求的响应状态码。这个方法需要在发送响应头前调用。
ngx.say(...)                    -- 与 ngx.print 相同,同时末尾添加一个回车符
ngx.exit(status)                -- 结束请求

ngx.time()                      -- 返回从1970年到现在经过的秒数。
ngx.now()                       -- 返回一个从1970年到现在经过的秒数,浮点型的数字,小数部分是毫秒
ngx.update_time()               -- 强行更新Nginx当前时间缓存,涉及系统调用,有一些系统开销
ngx.timer.at(delay, callback, user_arg1, ...)		-- 创建一个 Nginx 定时器
ngx.sleep                       -- 无阻塞休眠(使用定时器实现,事件精确到1毫秒)

ngx.worker.exiting()            -- nginx的worker进程退出
ngx.worker.pid()                -- 返回当前 Nginx 工作进程的进程 ID (PID)

ngx.decode_args(args)           -- 将 URI 编码的查询字符串解码为 Lua 表
ngx.encode_args(args)           -- 根据 URI 编码规则,将 Lua 表编码成一个查询参数字符串

ngx.location.capture(uri, options?)   -- 向 uri 发起一个同步非阻塞 Nginx 子请求。
ngx.unescape_uri(str)                 -- 将转义过的str解码

ngx.re.match((subject, regex, options?, ctx?, res_table?))  -- 使用 Perl 兼容正则表达式 regex 匹配字符串 subject,并使用可选的参数 options 作为正则表达式选项。
ngx.re.sub(subject, regex, replace, options?)               -- 使用 Perl 兼容正则表达式 regex 匹配字符串 subject,将第一个结果替换为字符串或函数类型参数

replace ngx.socket.tcp()    -- 创建并得到一个 TCP 或 unix 域流式 socket 对象
ngx.socket.udp()            -- 创建并得到一个 UDP 或 unix 域数据报 socket 对象