Lua 是一种轻量小巧的脚本语言
应用场景
游戏开发
独立应用脚本
Web 应用脚本
扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench
安全系统,如入侵检测系统
环境安装
- linux:下载源码包并在终端解压编译即可
curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz
tar zxf lua-5.3.0.tar.gz
cd lua-5.3.0
make linux test
make install
- window:
https://github.com/rjpcomputing/luaforwindows/releases
两种编程模式
- 交互式编程:Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用:
$ lua -i
$ Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio
> print("Hello World!")
Hello World!
>
- 脚本式编程:将程序写在文件中,该文件以 lua 为后缀名。
//在hello.lua文件中编写程序
print("Hello World!")
//执行hello.lua
lua hello.lua
Hello World!
注释
- 单行注释:
--
- 多行注释
--[[
多行注释
多行注释
--]]
变量
- 全局变量:在默认情况下,变量总是认为是全局的。全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。如果你想删除一个全局变量,只需要将变量赋值为nil。
- 数据类型
nil 这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean 包含两个值:false和true。
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。
注意:
1、type函数得到变量的数据类型
print(type("Hello world")) --> string
2、在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字:
> print("1" + 2)
3.0
> print("2" + 1)
3.0
3、字符串连接不使用 ‘ + ’,需使用 ‘ .. ’
print("wo" .. 'hu')
wohu
4、local b = 5 -- 前面+local成为局部,无论时是变量还是函数都可以加上local成局部变量和私有函数
5、
5.1、创建table:
tb = {} tb[2]="a"
or
tb = {1 , "23"} -->tb[1]=1,tb[2]="23"
or
tb = {foo = 3}-->tb[foo]=3
5.2、table中的索引可以时数值or字符串:
a = {}
a["key"] = "value"
key = 10
a[key] = 22
5.3、不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。
5.4、table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。
6、lua有许多方法可以对字符串进行操作,
如:string.upper("abc")将abc转换为大写,string.reverse(arg)翻转字符串
循环
当while判断为true时,执行循环体
while( true )
do
print("循环将永远执行下去")
end
exp1:初始值,exp2:目标值,exp3:步长
for var=exp1,exp2,exp3 do
<执行体>
end
//lua迭代器案例
a = {}
a["k1"] = "v1";
a[3] = 3;
for k, v in pairs(a) do
print(k .. " : " .. v) //k1:v1 3:3
end
先执行一次循环体,当condition为true时,退出循环
repeat
statements
until( condition )
注意:可以嵌套
如:
while( condition)
do
for var=exp1,exp2,exp3 do
<执行体>
end
end
if语句
if(布尔表达式)
then
--[ 布尔表达式为 true 时执行该语句块 --]
else
--[ 布尔表达式为 false 时执行该语句块 --]
end
函数
function max(num1, num2)
if (num1 > num2) then
result = num1;
else
result = num2;
end
return result;
end
模块与包
解决:如何在一个lua文件中使用另一个lua文件中的变量和函数?
1、编写一个模块。
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
-- 定义一个常量
module.constant = "这是一个常量"
-- 定义一个函数
function module.func1()
io.write("这是一个公有函数!\n")
end
local function func2()
print("这是一个私有函数!")
end
function module.func3()
func2()
end
return module
2、在其他lua文件中引用该模块。
//require("模块名")
require("module")
//调用模块中的变量和函数
print(module.constant)
module.func3()
注意:对于自定义的模块,模块文件不是放在哪个文件目录都行,函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。
编辑环境变量:export LUA_PATH="~/lua/?.lua;;"
使之生效:source ~/.profile
我们自定义的模块可以放置在该目录下,使用命令:cd ~ 可以进入该目录
面向对象
lua 中的 function 可以用来表示方法。那么LUA中的类可以通过 table + function 模拟出来。
我们需要先知道Lua 元表(Metatable)
在 Lua table 中我们可以访问对应的 key 来得到 value 值,但是却无法对两个 table 进行操作(比如相加)。
使用元表我们可以定义 Lua 如何计算两个 table 的相加操作 a+b。
- setmetatable(table,metatable): 对指定 table 设置元表(metatable)
- getmetatable(table): 返回对象的元表(metatable)。
- 设置元表:
mytable = setmetatable({m1},{m2})
把 m2 设为 m1 的元表 - __index 元方法:这是 metatable 最常用的键。当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
- 类
-- 元类
Rectangle = {area = 0, length = 0, breadth = 0}
-- 派生类的方法 new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
-- 派生类的方法 printArea
function Rectangle:printArea ()
print("矩形面积为 ",self.area)
end
- 创建对象
r = Rectangle:new(nil,10,20)
- 访问对象属性、方法
print(r.length)
r:printArea()
- 继承:使用上面的类
--首先创建对象,但调用方法时,不传入参数
Ex = Rectangle:new()
-- 继承类方法 new
function Ex:new (o,length,breadth)
o = o or Shape:new(o,length,breadth)
setmetatable(o, self)
self.__index = self
return o
end
--继承类的新的方法
function Ex:printArea ()
print("ex: ",self.area)
end
数据库访问
- 借助nginx+OpenResty访问mysql
luasql = require("resty.mysql")
--创建实例
--获取uri上的id
local param = ngx.req.get_uri_args()["id"]
local db, err = mysql:new()
--设置超时时间(毫秒)
db:set_timeout(1000)
--连接数据库
local props = {
host = "127.0.0.1",
port = 3306,
database = "db1",
user = "root",
password = "aabsabs"
}
local ok, err = db:connect(props)
local select_sql = " select * from test where id = "..param
--执行数据库操作
res,err = db:query(select_sql)
for i,row in ipairs(res) do
for name,id in pairs(row) do
ngx.say(name,":",id)
end
end
- 借助nginx+OpenResty访问redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
red:connect("127.0.0.1", 6379)
local res, err = red:get("key")
ngx.say("{ans:",res,"}")
return