LUA教程

教程

一、安卓

windows

下载 安装

安装后路径在:C:\Program Files (x86)\Lua\5.1\lua.exe 打开会进入终端,和python差不多
执行方式 lua test.lua

Pycharm 安装

Settings-plugins- 搜索 lua 安装,重启
配置执行路径:
Settings-Languages-Lua-加号-设置为default,eecutable设置为C:\Program Files (x86)\Lua\5.1\lua.exe

一、基本语法

注释

单行注释(两个减号):

-- 注释

多行注释(两个减号+中括号):

--[[

fefe
]]

全局变量

lua 全部都是全局变量,如果访问一个没有定义的全局变量,返回nil

二、数据类型

数据类型

lua是动态语言
有8个基本类型

  • nil 空
  • boolean false和true
  • string 字符串 单引号或双引号
  • number 数字
  • function 函数
  • userdata c数据结构
  • thread 独立线路,用于执行协同程序
  • table 关联数据,索引可以是数字,字符串和表类型
print(type(nil))
print(type(false))
print(type("string"))
print(type(12))
print(type(type))

t={} #定义空表
t[0]=1 #写入,索引可以是数字或者字符串
t["k"]=2
print(t[0]) # 读取
print(t["k"])
print(t.k) # 如果key是字符串,也可以这样访问
t2={1,2,3,4 } # 定义一个数组
print(t2[1])  #读取,下标从1开始,而不是0
print(t)

函数

用function....end定义一个函数

function f1(p1,p2)
    t={2,3}
    print(t[1])
    print(p1)
    print(p2)
end

f1(1,2)

三、变量

lua中全部变量是全局变量,如果定义前加local,变为局部变量


a=1
b=2
c=3

function f1()
    local d=4
    e=5
    a=11
    print(a)
    print(b)
    print(c)
    print(d)
end
f1()
print(a) -- a是11
print(b)
print(c)
print(d) -- 读不了d
print(e) -- 可以读e

四、循环

while

t=1
while t<10 do
    print(t)
    t=t+1
end

for

数值for循环

for var=exp1,exp2,exp3 do  
    <执行体>  
end 

和c的for一样,exp3是可选,默认1

for i=1,10,2 do
    print(i)
end

泛型for循环

t={'key1','key2'}
for i,v in ipairs(t) do
    print(i,v)
end

  • i是下标,从1开始
  • v是数组的值
  • 如果下标和key都遍历,ipairs改为

repeat until

t=1
repeat
    print(t)
    t=t+1
until (t>9)

流程控制

t=1
-- if结构
if (t==1) 
    then
    print(t,">1")
end

-- if else 结构
if (t>1) 
    then
    print(t,">1")
else
    print(t,"<=1")

end
-- if elif else 结构
if (t>1)
    then
    print(t,">1")
elseif (t==1)
    then
    print(t,"=1")
else
    print(t,"<1")

end
  • if 和 elseif后面都要加then,else不用,后面加end

函数

optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
    function_body
    return result_params_comma_separated
end
  • optional_function_scope 表示函数是全局的还是局部的变量。如果局部,加local
  • function_name 函数名
  • argument1 函数入参
  • result_params_comma_separated 函数出参,可以多值

例子:

function f1(p)
    return p+1
end
print(f1(2))

多返回值例子:

function f2(p)
    return p+1,p+2
end
a,b=f2(2)
print(a)
print(b)

可变入参例子:

function f3(...)
    local args = { ... }
    print(select("#",...)) -- 查看参数个数
    a=select(1,...) -- 也可以这样读取第n个参数
    print(a)
    print(args[1])
    print(args[2])
end

f3(10, 11, 12)
  • 定义函数时,入参设置为...,然后转换...为表,最好定义为局部变量

运算符

算术运算符

        • / % ^ -

关系运算符

  • ==
  • ~= 不等于
  • <
  • =

  • <=

逻辑运算符

  • and
  • or
  • not

一元运算符

  • .. 连接两个字符串
  • 返回字符串长度

字符串

定义

  • 单引号
  • 双引号
  • [[]]之间

字符串操作

print(string.upper('aaa')) --转换大写
print(string.lower('BBB')) --转换小写
print(string.gsub('abc', 'a', '2', 3)) --替换
print(string.find('abc', 'a')) --找字符
print(string.reverse('abc')) --反转
print(string.format('aaa:%s', 4)) --格式化字符串
print(string.len('aaa:%s')) --字符串长度
print(string.gmatch("Hello Lua user", "%a+")) --返回迭代器,返回所有查找到的自传
print(string.match("I have 2 questions for you.", "%d+ %a+")) --全匹配
print(string.sub("I have 2 questions for you.", 0, 1)) --截取

操作

t={1,2,3,4}
print(table.concat(t,',')) --数组转换为字符串
table.insert(t,2,6)-- 插入
t[6]=11
print(table.maxn(t)) --最大的key
table.remove(t,1) --移除 pos参数默认最后一位
print(table.sort(t)) --排序

模块

module.lua

module={}
module.param='a'
function module.func1()
    print('module.func1')

end
function func3()
    print('module.func1')

end
return module

1.lua

require('module')
module.func1()
print(module.param)

找包的顺序

  1. lua的执行程序目录,即C:\Program Files (x86)\Lua\5.1\lua\
  2. 环境变量 LUA_PATH export LUA_PATH="~/lua/?.lua;;"

网络

如果报错:no resolver defined to resolve
在nginx的http里面加配置:resolver 8.8.8.8;

local httpc = http.new()
local url='http://www.kugou.com'
local res,err=httpc:request_uri(url,{
	method='GET', --请求方法
	body="", --请求体
	headers={  -- 请求头
		['Content-Type']="application/json"
	}
})
ngx.log(ngx.ERR,tostring(err)) --错误信息
ngx.log(ngx.ERR,tostring(res.status))-- http状态码
ngx.log(ngx.ERR,tostring(res.body)) -- body 字符串
ngx.log(ngx.ERR,tostring(res.headers)) -- 返回头 table

其他操作

赋值

or 赋值

or 赋值和Python类似,但是0不属于nil,如果a=nil 或者false 会取后面的值

local a=nil or 0 or 1 -- a=0
local a=0 or nil or 1 -- a=0

and or

a = nil
b = a == nil and 1 or 2 -- 1
b = a ~= nil and 1 or 2 -- 2
print(b)

_G
_G类似python的globals,保存全部的全局变量

a = 1
print(_G.a)

table.foreach

类似python的map。f不能return 不然foreach就会

function f(index, value)
    print(index)
    print(value)
end
table.foreach(t, f)
table.foreach(t, print)

继承

lua没有类的概念,只能通过表来实现类。
而怎么实现类的继承呢?

t1 = {
    a = 1
}

t2 = {
    b = 2
}
t1.__index = t1
setmetatable(t2, t1)
print(t2.a)
  • t1是否父类,t2是子类,要实现t2继承t1,可以这样做
  • 设置t1的元表属性为自身
  • 设置t1为t2的元表
  • 当访问t2的a属性
    • 先查看t2是否有a属性,发现没有
    • 查看t2是否有元表,发现有,是t1
    • 这时不是直接访问t1的a变量,而是访问t1的__index,发现非空
    • 访问__index.a得到1,所以t2.a=1

如果只想查看t2是否有a属性,不需要管元表,可以使用rawget(t2,'a')

rediscluster库学习

  • rediscluster的底层是redis,redis的底层是tcp。ngx.tcp文档:文档
  • 通过init(),会初始化实例,包括:
    • 设置cmd,为自动执行do_cmd函数
    • 设置cluster命令
    • 设置asking命令
  • 通过new_cluster函数,生成一个客户端单例实例,保存在rediscluster.__cluster,
    • 继承rediscluster的_M

    • 里面有2个属性:

      • config 就是new_clusterr的入参conf
      • cluster 就是 通过cluster_new 函数生成的实例,继承rediscluster._cluster(注意_cluster和__cluster不一样)。初始化时会执行_cluster.Update更新曹位
  • 当执行例如get
    • 执行_cmd_exce函数
    • 通过key计算槽位
    • 通过槽位找到对应的ip和port
    • 实例化一个redis实例,并设置ip和port
    • 和对应的ip port建立tcp连接
    • redis实例执行命令,获得返回值
    • 通过setkeepalive,让tcp连接返回连接池

lua_code_cache off; 参数

当设置了该参数,nginx不会缓存lua代码和变量(_M和单例等),也就是每次请求都是一个全新的请求,包括redis的槽位,_M设置的变量都需要重新设置。

性能测试

Python:

start=time.time()
s=0
for i in xrange(100000000):
    s=s+i
print s
print time.time()-start

4999999950000000
11.1540000439

Lua:

local socket = require "socket"
local start=socket.gettime()
local s=0
for i=1,100000000 do
    s=s+i
end
print(s)
print(socket.gettime()-start)

5.00000005e+015
0.91710901260376

lua的计算性能是python的10倍

posted @ 2021-04-09 18:26  Xjng  阅读(1465)  评论(0编辑  收藏  举报