- 学习背景: 一直想去体验下openrestry,可惜一直没动力去完成这件事,正好工作原因需要调研,就开启体验之旅吧。开始前需要对lua语法有简单了解和认识
- 流水式计划:
- 基础语法简单熟悉
- openrestry模块知识点实践
- 一个小项目
- 致谢码洞公众号老钱界面排版经验传授
lua基础语法
代码语言:javascript复制print("hello lua")
获取数据类型 函数type
代码语言:javascript复制a = 123
print(type(a)) -->output:number
print(type(1.23)) -->output:number
print(type(nil)) -->output:nil
print(type('123')) -->output:string
print(type(true)) -->output:boolean
a = {}
print(type(a)) -->output:table
local b
print(b) -->output:nil 默认nil
代码语言:javascript复制 以上出现了几个关键词简单描述下:
1. local相当于声明变量b为局部变量
2. --为单行注释 --[[ code ]]为多行注释
代码语言:javascript复制local a = 0
if a then
print('pass') --output:pass
end
代码语言:javascript复制local b
if b then
print('pass')
else
print('no pass') --output:no pass
end
代码语言:javascript复制local a=false
if a then
print('pass')
else
print('no pass') --output:no pass
end
代码语言:javascript复制在lua中,nil和false为假,其他所有值为真 比如0和空字符串都为真
local a = 5
local b = 3
function getNumber()
if a>b then
return a
else
return b
end
end
value = getNumber()
print(value)
代码语言:javascript复制声明a,b两个全局变量,声明了一个函数返回最大值,其中需要注意的就是lua是没有函数提升的概念的,所以需要先声明后使用
local a = 5
local b = 3
function getNumber(a,b)
if a>b then
return a
else
return b
end
end
value = getNumber(a,b 3)
print(value) //output:6
代码语言:javascript复制local a = 5
local b = 3
function getNumber()
local b = 10
if a>b then
return a
else
return b
end
end
value = getNumber()
print(value) --output:10
函数中的b作用于函数块内,覆盖外部b的变量值
Math函数库
代码语言:javascript复制a = 1.2
print(math.floor(a)) --output : 1
print(math.ceil(a)) --output : 2
print(math.abs(a)) --output : 1.2
print(math.random(20,30)) --output : 随机
print(math.max(1,2,3,4,8,5,0)) --output : 8
print(math.min(1,2,3,4,8,5,0)) --output : 0
代码语言:javascript复制lua并没有四舍五入,如果实现可以使用math.floor
lua 中的math.floor函数是向下取整函数。
math.floor(5.123) -- 5
math.floor(5.523) -- 5
用此特性实现四舍五入
math.floor(5.123 0.5) --5
math.floor(5.523 0.5) --6
也就是对math.floor函数的参数进行 “ 0.5” 计算
String函数库
代码语言:javascript复制s = 'abcd123'
print(string.len(s)) --output : 7
print(string.rep(s,2)) --output : abcd123abcd123
print(string.lower(s)) --output : abcd123
print(string.upper(s)) --output : ABCD123
print(string.sub(s,1,2)) --output : ab
local find = string.find
print(find('abcd haha 123','a',2)) --output:7
print(find('abcd haha 123','az',2)) --output:nil
print(string.format('%d',2.5 )) --output : 2
print(string.format("%.2f",1.256)); --output : 1.26
print(string.format('value: %s',s )) --output : value: abcd123
注意 string.sub 从1开始截取,截取2个字符。lua下标是从1开始的 %.2f也可以实现四舍五入
新类型-强大的talbe
代码语言:javascript复制local user = {
name = "xiao ge ge",
age = {
1,2,3
}
}
print(user.name) --output : xiao ge ge
print(user.age[1]) --output : 1
local class = {'one class','two class'}
print(class[0]) --output : nil
print(class[1]) --output : one class
day1 = {2018,7,1,0,0,0}
print(#(day1)) --获取长度 6
print(table.getn(day1)) --获取长度 6
print(next(day1)) --验证是否为空
table函数库
代码语言:javascript复制tbl = {"alpha", "beta", "gamma"}
print(table.concat(tbl, ":")) --output: alpha:beta:gamma
print(table.concat(tbl, nil, 1, 2)) --output: alphabeta
print(table.concat(tbl, "n", 2, 3)) --output: beta n gamma
代码语言:javascript复制tbl = {"a", "b", "c"}
table.insert(tbl, "d")
print(table.concat(tbl,",")) --output: a,b,c,d
table.insert(tbl, "e")
print(table.concat(tbl,",")) --output: a,b,c,d,e
代码语言:javascript复制class = {1,2,3,4,5}
max = table.maxn(class);
print(max) --output: 5
代码语言:javascript复制class = {1,2,3,4,5,6}
max = table.remove(class);
print(max) --output: 6
print(table.concat(class,',')) --1,2,3,4,5
remove相当于其他语言的pop,移除最后一位
入栈 出栈操作
代码语言:javascript复制list = {'a','b','c'}
table.insert(list,'d'); --进栈
print(table.concat(list,',')) --a,b,c,d
table.remove(list) --出栈
print(table.concat(list,',')) --a,b,c
队列操作
代码语言:javascript复制list = {'a','b','c'}
table.insert(list,1,'1'); --入队列 注意下标1
print(table.concat(list,',')) --1,a,b,c
table.remove(list) --出队列
print(table.concat(list,',')) --1,a,b
日期时间函数
uninx时间戳
代码语言:javascript复制print(os.time()) --output : unix时间戳
day1 = {year=2018,month=7,day=1,hour=0,min=0,sec=0}
day1_time = os.time(day1) --output: 获取day1时间戳
day2 = {year=2018,month=7,day=1,hour=0,min=1,sec=0}
day2_time = os.time(day2)
print(os.difftime(day1_time,day2_time)) --day1-day2=-60
时间戳转时间
代码语言:javascript复制 temp = os.date("*t", 906000490)
--{year = 1998, month = 9, day = 16, yday = 259, wday = 4,hour = 23, min = 48, sec = 10, isdst = false}
date = os.date('%Y-%m-%d %H:%M:%S',os.time())
print(date) --output: 2018-07-01 06:19:11
lua条件判断
关系运算符 | 说明 |
---|---|
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
== | 等于 |
~= | 不等于 |
代码语言:javascript复制在使用"=="做等于判断时,要注意对于table,userdata和函数,lua是作引用比较的。也就是说,只有当两个变量引用同一个对象时,才认为他们相等。
listA = {'a','b','c'}
listB = {'a','b','c'}
print(listA==listB) --output false
代码语言:javascript复制local a,b,c = nil,2,3 --类似go的多赋值
print(a and b) --output: nil
print(a or b or c) --output: 2
print(not a) --output true
代码语言:javascript复制上面用例and or在C语言会返回0或1,但是lua中a and b如果a为nil,则返回a 否则返回b, a or b中如果a为nil,则返回b否则返回a
function getList(users)
local temp = ''
for k,v in ipairs(users) do
temp = temp..'n'..k..'=>'..v
end
return 'ok',temp
end
users = {1,2,nil,4,5,6}
msg,temp = getList(users) --output: ok 1=>1 n 2=>2
print(msg,temp)
代码语言:javascript复制function getList(users)
local temp = ''
for k,v in pairs(users) do
temp = temp..'n'..k..'=>'..v
end
return 'ok',temp
end
users = {1,2,nil,4,5,6}
msg,temp = getList(users) --output: ok 1=>1 2=>2 4=>4 5=>5 6=>6
print(msg,temp)
两段代码看似一样,但其实体现了ipairs和pairs的区别,ipairs遇到nil会终止,而pairs会跳过。 并且此示例程序还演示了多返回值的写法,和go很类似 接收值_可忽略参数 迭代文件中每行io.lines 迭代table pairs 迭代数组ipairs 迭代单词string.gmatch
控制结构
if else elseif for while break
代码语言:javascript复制x = 1
sum = 0
while x<= 5 do
sum = sum 1
x = x 1
end
print(sum) --output: 5
代码语言:javascript复制for x=0,5,1 do
while true do
if x % 2 == 0 then
break
end
print(x)
x = x 1
end
end
--output 1 3 5
lua是没有continue,上面代码变相实现了continue的功能,翻译下for循环可能就是我们常见的 for x=0;x<=5;x 操作。循环代码跟do关键字 条件判断为then
类似 do-while 循环
代码语言:javascript复制x = 10
repeat
print(x)
until false
只有until为真才能退出,正好与C相反
函数的例子
代码语言:javascript复制foo = {}
foo.bar = function(a,b,c)
print(a,b,c) --output: 1 2 3
end
foo.bar(1,2,3);
可变长参数
代码语言:javascript复制function func(...)
local temp = {...}
print(table.concat(temp,',')) --output: 1,2,3,4
end
func(1,2,3,4)
代码语言:javascript复制--更简化的循环遍历
myTable = {1,2,3,4,5}
sum = 0
for index = 1,#myTable do
sum = sum myTable[index]
end
print(sum) --output:15
小tips
代码语言:javascript复制在参数传递过程中 当函数参数是table类型时,是按引用传递的,其他都是按赋值传递的。这点也和go有类似之处
function func(name,...)
print(name) --ouput: xiaoming
print(type(...)) --output: number
print(select('#',...)) --output: 4 获取长度
print(select(3,...)) --output: 3 4 从第三个位置开始返回
end
func('xiaoming',1,2,3,4)
lua模块
test.lua
代码语言:javascript复制local test = {}
name = 'xiaming'
age = 12
user = {name=name,age=age}
function getUser()
return user.name,user.age
end
function test.getList()
return 'list','list';
end
return test
main.lua
代码语言:javascript复制test = require('test')
print(name) --output: xiaoming 可以直接使用
val1,val2 = getUser() --output: xiaming 12
test.getList() --output: list,list
print(val1,val2)
上面简单示例了两种函数使用方式 getUser 和test.getList,推荐第二种写法,如果相同函数名的话后面会覆盖掉前面的
Lua 元表(Metatable)
_index 源方法
代码语言:javascript复制当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
other = {key3=10,key4=20}
mytable = setmetatable({key1=1,key3=3},{__index=other})
print(mytable.key4) --output: 20
for k,v in pairs(mytable) do
print(k..'=>'..v)
end
--output : 1 3
同时可以使用函数逻辑处理
代码语言:javascript复制 mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
})
print(mytable.key1,mytable.key2)
__newindex 元方法
代码语言:javascript复制__newindex 元方法用来对表更新,__index则用来对表访问 。当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
代码语言:javascript复制mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, """..value..""")
end
})
为表添加操作符 文档页面: http://www.runoob.com/lua/lua-metatables.html
__tostring 元方法
代码语言:javascript复制other = {key3=10,key4=20}
mytable = setmetatable({key1=1,key3=3},{
__index=other,
__tostring = function(mytable)
return 'todo处理'
end
})
print(mytable.key4) --output: 20
print(mytable) --output: todo处理
lua面向对象
lua的对象支持给人的第一感觉不像是以前所认知的面向对象写法,而大部分是table function的一种组合
代码语言:javascript复制obj = {name='lili'}
function obj.getName()
return obj.name
end
ret = obj.getName()
print(ret) --output: lili
代码语言:javascript复制Company = {title='',seo='',content=''}
function Company:new (title,seo,content)
o = {} --此处为真正的创建一个新对象
setmetatable(o, self)
self.__index = self --将self绑定到o这个新对象上
self.title = title or ''
self.seo = seo or ''
self.content = content or ''
return o --返回新对象
end
function Company:getInfo()
return string.format('title-seo-content: %s %s %s',self.title,self.seo,self.content );
end
obj = Company:new(1,2,3)
print(obj.title) --output: 1
ret = obj:getInfo()
print(ret) --output: title-seo-content: 1 2 3
:是lua面向对象的语法糖。Account:new(conf)等同于Account.new(self, conf),相当于将调用者自身当做第一个参数,使用冒号调用就相当于隐式地传递self参数。
参考部分连接整理
菜鸟教程 面向对象解释 Metatable