Lua入门记录

时间:2022-12-28 20:36:15

学习资料

阅读笔记,只是记录了知识点和一些注意点,详细的看上面提供的学习资料链接

  • Lua 基础数据类型

    • nil(空)
    • boolean(布尔)
      • Lua 中 nil 和 false 为“假”,其它所有值均为“真”
    • number(数字)
    • string(字符串)
      • 使用一对匹配的单引号。例:'hello'。
      • 使用一对匹配的双引号。例:"abclua"。
      • 字符串还可以用一种长括号(即[[ ]])括起来的方式定义
      • Lua 字符串一般都会经历一个“内化”(intern)的过程,即两个完全一样的 Lua 字符串在 Lua 虚拟机中只会存储一份
    • table (表)
      • 索引可以是除 nil 以外的任意类型的值
    • function (函数)
      • 有名函数的定义本质上是匿名函数对变量的赋值
  • 表达式

    • 算术运算符
    • 关系运算符
      • Lua 语言中“不等于”运算符的写法为:~=
      • 只有当两个变量引用同一个对象时,才认为它们相等
    • 逻辑运算符
      • a and b 如果 a 为 nil,则返回 a,否则返回 b (短路求值)
      • a or b 如果 a 为 nil,则返回 b,否则返回 a (短路求值)
      • 对于 not,永远只返回 true 或者 false
    • 字符串连接
      • 连接两个字符串,可以使用操作符".."(两个点)
      • 使用 string 库函数 string.format 连接字符串
      • 由于 Lua 字符串本质上是只读的,因此字符串连接运算符几乎总会创建一个新的(更大的)字符串
      • 使用table.concat() 来进行很多字符串的拼接
    • 优先级
      • 若不确定某些操作符的优先级,就应显示地用括号来指定运算顺序。这样做还可以提高代码的可读性。
    • 正则表达式
      • 使用ngx.re.*进行正则处理
          -- 参数 "j" 启用 JIT 编译,参数 "o" 是开启缓存必须的
      local m = ngx.re.match("hello, 1234", regex, "jo")
  • 控制结构

    • if-else
      • else 与 if 是连在一起的,若将 else 与 if 写成 "else if" 则相当于在 else 里嵌套另一个 if 语句
    • while
    • repeat
      • 执行 repeat 循环体后,直到 until 的条件为真时才结束
    • for
      • Lua 标准库提供了几种迭代器,包括用于迭代文件中每行的(io.lines)、 迭代 table 元素的(pairs)、迭代数组元素的(ipairs)、迭代字符串中单词的(string.gmatch)
      • 最好使用ipairs,ipairs() 内建函数是可以被 JIT 编译的
    • break,return 和 goto
      • return 若要写在函数中间,则只能写在一个显式的语句块内 或者 直接写成do return end,否则会报错
      • 提供 goto 代替 continue
  • Lua函数

    • 使用local修饰符标记局部函数
    • 变长参数使用"..."(三个点),若对性能敏感的代码,应当避免使用此种形式
    • 函数的返回值允许函数返回多个值,返回多个值时,值之间用","隔开
    • 全动态函数调用
        local args = {...} or {}
    method_name(unpack(args, 1, table.maxn(args)))
    • 点号与冒号操作符的区别
      • 冒号操作会带入一个 self 参数,用来代表 自己,冒号的操作,只有当变量是类对象时才需要
      • 点号操作,只是 内容 的展开
          local str = "abcde"
      print("case 1:", str:sub(1, 2))
      print("case 2:", str.sub(str, 1, 2))
  • 模块

    • require 函数用来加载模块,禁用module() 定义模块
    • require 函数内不能进行上下文切换,所以不能够在模块的*上下文中调用 cosocket 一类的 API
    • 局部变量
      • Lua 中的局部变量要用 local 关键字来显式定义,不使用 local 显式定义的变量就是全局变量
      • Lua 上下文中应当严格避免使用自己定义的全局变量。
      可以使用一个 lj-releng 工具来扫描 Lua 代码,定位使用 Lua 全局变量的地方。
      lj-releng 的相关链接:https://github.com/openresty/openresty-devel-utils/blob/master/lj-releng
    • 虚变量
      • 按照惯例以一个下划线(“_”)来命名,用它来表示丢弃不需要的数值,仅仅起到占位的作用
    • 非空判断
      • 对于简单类型的变量,我们可以用 if (var == nil) then 这样的简单句子来判断
      • 判断一个 table 是否为 {}
      function isTableEmpty(t)
      return t == nil or next(t) == nil
      end
  • String库

    • Lua 字符串内部用来标识各个组成字节的下标是从 1 开始的
    • string.byte(s [, i [, j ]])
    • string.char (...)
    • string.upper(s)
    • string.lower(s)
    • string.len(s)
      • 使用此函数是不推荐的。应当总是使用 # 运算符来获取 Lua 字符串的长度。
    • string.find(s, p [, init [, plain]])
      • p参数尽量不要使用模式匹配
    • string.format(formatstring, ...)
    • string.match(s, p [, init])
      • 目前并不能被 JIT 编译,应 尽量 使用 ngx_lua 模块提供的 ngx.re.match 等接口
    • string.gmatch(s, p)
      • 目前并不能被 LuaJIT 所 JIT 编译,而只能被解释执行。应 尽量 使用 ngx_lua 模块提供的 ngx.re.gmatch 等接口。
    • string.rep(s, n)
    • string.sub(s, i [, j])
    • string.gsub(s, p, r [, n])
      • 此函数不能为 LuaJIT 所 JIT 编译,而只能被解释执行。一般我们推荐使用 ngx_lua 模块提供的 ngx.re.gsub 函数。
    • string.reverse (s)
  • table库

    • 下标从 1 开始
    • 取长度操作符写作一元操作 #
    • 判断数组大小
      • table.getn(t) 计算的是数组元素,不包括 hash 键值,以第一个 nil 元素来判断数组结束
      • # 只计算 array 的元素个数,实际上调用了对象的 metatable 的 __len 函数
      • 一定不要使用 # 操作符或 table.getn 来计算包含 nil 的数组长度
      • 不要在 Lua 的 table 中使用 nil 值,如果一个元素要删除,直接 remove,不要用 nil 去代替
    • table.getn 获取长度
      • 对于有“空洞nil值”的情况,table 的长度存在一定的 不可确定性。
    • table.concat (table [, sep [, i [, j ] ] ])
    • table.insert (table, [pos ,] value)
    • table.maxn (table)
    • table.remove (table [, pos])
    • table.sort (table [, comp])
    • table.new 预分配 Lua table 空间
    • table.clear 释放 table 空间
  • 日期时间函数

    推荐使用 ngx_lua 模块提供的带缓存的时间接口,如 ngx.today, ngx.time, ngx.utctime, ngx.localtime, ngx.now, ngx.http_time,以及 ngx.cookie_time 等
    • os.time ([table])
    • os.difftime (t2, t1)
    • os.date ([format [, time]])
  • 数学库

    • math.rad(x) 角度x转换成弧度
    • math.deg(x) 弧度x转换成角度
    • math.max(x, ...) 返回参数中值最大的那个数,参数必须是number型
    • math.min(x, ...) 返回参数中值最小的那个数,参数必须是number型
    • math.random ([m [, n]]) 不传入参数时,返回 一个在区间[0,1)内均匀分布的伪随机实数;只使用一个整数参数m时,返回一个在区间[1, m]内均匀分布的伪随机整数;使用两个整数参数时,返回一个在区间[m, n]内均匀分布的伪随机整数
    • math.randomseed (x) 为伪随机数生成器设置一个种子x,相同的种子将会生成相同的数字序列
    • math.abs(x) 返回x的绝对值
    • math.fmod(x, y) 返回 x对y取余数
    • math.pow(x, y) 返回x的y次方
    • math.sqrt(x) 返回x的算术平方根
    • math.exp(x) 返回自然数e的x次方
    • math.log(x) 返回x的自然对数
    • math.log10(x) 返回以10为底,x的对数
    • math.floor(x) 返回最大且不大于x的整数
    • math.ceil(x) 返回最小且不小于x的整数
    • math.pi 圆周率
    • math.sin(x) 求弧度x的正弦值
    • math.cos(x) 求弧度x的余弦值
    • math.tan(x) 求弧度x的正切值
    • math.asin(x) 求x的反正弦值
    • math.acos(x) 求x的反余弦值
    • math.atan(x) 求x的反正切值
  • 文件操作

    实际中的应用,在 OpenResty 项目中应尽可能让网络处理部分、文件 I/0 操作部分相互独立,不要揉和在一起
    • io.open (filename [, mode])
    • file:close ()
    • io.close ([file])
    • file:flush ()
    • io.flush ()
    • io.input ([file])
    • file:lines ()
    • io.lines ([filename])
    • io.output ([file])
    • file:read (...)
    • io.read (...)
    • io.type (obj)
    • file:write (...)
    • io.write (...)
    • file:seek ([whence] [, offset])
    • file:setvbuf (mode [, size])
  • 元表

    • 元表 (metatable) 的表现行为类似于 C++ 语言中的操作符重载
    • 两个十分重要的用来处理元表的方法
      • setmetatable(table, metatable):此方法用于为一个表设置元表。
      • getmetatable(table):此方法用于获取表的元表对象。
    • 可被重载的元方法
      元方法 含义
      __add + 操作
      __sub - 操作 其行为类似于 "add" 操作
      __mul * 操作 其行为类似于 "add" 操作
      __div / 操作 其行为类似于 "add" 操作
      __mod % 操作 其行为类似于 "add" 操作
      __pow ^ (幂)操作 其行为类似于 "add" 操作
      __unm 一元 - 操作
      __concat .. (字符串连接)操作
      __len # 操作
      __eq == 操作 函数 getcomphandler 定义了 Lua 怎样选择一个处理器来作比较操作 仅在两个对象类型相同且有对应操作相同的元方法时才起效
      __lt < 操作
      __le <= 操作
      __index 取下标操作用于访问 table[key]
      __newindex 赋值给指定下标 table[key] = value
      __tostring 转换成字符串
      __call 当 Lua 调用一个值时调用
      __mode 用于弱表(week table)
      __metatable 用于保护metatable不被访问
  • Lua 面向对象编程

      • 使用表和函数实现面向对象
    • 继承
      • 用元表实现
    • 成员私有性
      • 使用类似于函数闭包的形式来实现
  • FFI

    • FFI 库,是 LuaJIT 中最重要的一个扩展库

    • 词库解释

      名词 解释
      cdecl A definition of an abstract C type(actually, is a lua string)
      ctype C type object
      cdata C data object
      ct C type format, is a template object, may be cdecl, cdata, ctype
      cb callback object
      VLA An array of variable length
      VLS A structure of variable length
    • 在 lua 文件中使用 ffi 库的时候,必须要有这一行:local ffi = require "ffi"

    • ffi.cdef

      • 语法:ffi.cdef(def)
      • 功能:声明 C 函数或者 C 的数据结构
    • ffi.typeof

      • 语法:ffi.cdef(def)
      • 功能:创建一个 ctype 对象,会解析一个抽象的 C 类型定义
    • ffi.new

      • 语法:cdata = ffi.new(ct [,nelem] [,init...])
      • 功能:开辟空间,第一个参数为 ctype 对象,ctype 对象最好通过 ctype = ffi.typeof(ct) 构建
    • ffi.fill

      • 语法:ffi.fill(dst, len [,c])
      • 功能:填充数据
    • ffi.cast

      • 语法:cdata = ffi.cast(ct, init)
      • 功能:创建一个 scalar cdata 对象。
    • 调用 C 函数

      1. 加载 FFI 库。
      2. 为函数增加一个函数声明。这个包含在 中括号 对之间的部分,是标准 C 语法。
      3. 调用命名的 C 函数
          local ffi = require("ffi")
      
          ffi.cdef[[
      int printf(const char *fmt, ...);
      ]] ffi.C.printf("Hello %s!", "world")
    • 防止内存泄漏的方案

      1. 在调用 resource = ffi.C.xx_create 等申请资源的函数之后,立即补上一行 ffi.gc(resource, ...) 来注册释放资源的函数
      2. 有些时候,ffi.C.xx_create 返回的不是具体的 cdata,而是整型的 handle。这会儿需要用 ffi.metatype 把 ffi.gc 包装一下
        local resource_type = ffi.metatype("struct {int handle;}", {
        __gc = free_resource
        }) local function free_resource(handle)
        ...
        end resource = ffi.new(resource_type)
        resource.handle = ffi.C.xx_create()
  • JIT

    可以通过 ngx-lj-gc-objs 工具看到指定的 Nginx worker 进程里所有 trace 对象的一些基本的统计信息:https://github.com/openresty/stapxx#ngx-lj-gc-objs
    
    我们如何才能知道具体是哪一行 Lua 代码上的哪一个 NYI 原语终止了 trace 编译呢?
    答案很简单。就是使用 LuaJIT 安装自带的 jit.v 和 jit.dump 这两个 Lua 模块。这两个 Lua 模块会打印出 JIT 编译器工作的细节过程 完整的 NYI 列表:http://wiki.luajit.org/NYI 可以使用 ab 和 weighttp 这样的工具对相应的服务接口进行预热,以触发 LuaJIT 的 JIT 编译器开始工作

Lua入门记录的更多相关文章

  1. 续关于C&num;的微信开发的入门记录一

    前几天写了一篇博客<关于C#的微信开发的入门记录一>,原文地址:http://www.cnblogs.com/zhankui/p/4515905.html,现在继续完善: 目前很多小伙伴都 ...

  2. lua入门demo(HelloWorld&plus;redis读取)

    1. lua入门demo 1.1. 入门之Hello World!! 由于我习惯用docker安装各种软件,这次的lua脚本也是运行在docker容器上 openresty是nginx+lua的各种模 ...

  3. ES 入门记录之 match和term查询的区别

    ElasticSearch 系列文章 1 ES 入门之一 安装ElasticSearcha 2 ES 记录之如何创建一个索引映射 3 ElasticSearch 学习记录之Text keyword 两 ...

  4. Linux 入门记录:二十、Linux 包管理工具 YUM

    一.YUM(Yellowdog Updater, Modified) 1. YUM 简介 RPM 软件包形式管理软件虽然方便,但是需要手动解决软件包的依赖问题.很多时候安装一个软件首先需要安装 1 个 ...

  5. Openresty最佳案例 &vert; 第2篇:Lua入门

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616622 本文出自方志朋的博客 什么是lua Lua 是一种轻量小巧的脚本语言,用标准 ...

  6. &lbrack;2017&period;02&period;07&rsqb; Lua入门学习记录

    #!/home/auss/Projects/Qt/annotated/lua -- 这是第一次系统学习Lua语言 --[[ 参考资料: 1. [Lua简明教程](http://coolshell.cn ...

  7. &lbrack;置顶&rsqb; 轻量级语言Lua入门

    作为一个脚本爱好者,而且是脚本(Perl)起家的我,一有空就喜欢学习下这些脚本语言.据说魔兽世界.愤怒小鸟都用到了它,所以今天研究下Lua这个叫法有点奇特的脚本 [转载请注明出处:http://blo ...

  8. Cordova 快速入门记录

    本篇文章由:http://xinpure.com/cordova-quick-start-recording/ 记一笔 Cordova 官网入门文档 Get Started Fast,言简意该.通俗易 ...

  9. Oracle触发器简单入门记录

    写在前面: 最近,老项目新增了日报优化的需求,丽姐让我用触发器去实现当数据插入或者更新的时候,实现对日报表数据更新操作.嗯嗯嗯呢,之前学习数据库的时候,有碰到过触发器,但都是一跳而过,也没怎么去真正的 ...

随机推荐

  1. 自实现CAS原理JAVA版,模拟下单库存扣减

    在做电商系统时,库存是一个非常严格的数据,根据CAS(check and swap)原来下面对库存扣减提供两种方法,一种是redis,一种用java实现CAS. 第一种 redis实现: 以下这个类是 ...

  2. Ubuntu 16&period;10下的eclipse

    下载后解压,放到文件下,打开此文件左边齿轮状的东西,即可指引安装:

  3. maven项目报:An error occurred while filtering resources

    maven项目在problem中报: An error occurred while filtering resources   解决方法: 右键项目-maven-update project.. 

  4. ngrok 2016版

    1. 先到http://www.ngrok.cc/下载客户端 2.进管理页面 注册登录 3.绑定域名 新增: 复制客户端id 打开该目录 按住shift 右键->在此处打开命令窗口 输入 sta ...

  5. 杭电ACM2092--整数解

    杭电ACM2092--整数解    分析 http://acm.hdu.edu.cn/showproblem.php?pid=2092 一个YES,一个Yes.试了10几次..我也是无语了..哪里都不 ...

  6. &lbrack;整理&rsqb;DLL延时加载 &amp&semi;&amp&semi; 设置进程私有环境变量

    DLL延时加载鉴于静态和动态加载之间,即无需在代码中显示加载但它内队依然是动态加载的方式只是系统帮处理了.这样做好处是: 1. 可以加快启动时间(因为它是动态加载在需要的时间加载), 2. 减小编写L ...

  7. C&plus;&plus;STL的简单使用

    #include <iostream>#include <vector>#include<deque>#include <list>#include&l ...

  8. 64位win8&period;1系统 运行 32位程序,文件夹路径是中文遇到问题

    今天有一位用户向我反应软件使用遇到问题. 用户使用的是64位win8.1系统,之前有很多用户使用64位的win8.1系统没遇到过问题. 远程协助了一下,差不多15分钟我试了几个办法没解决问题. 最后我 ...

  9. &lbrack;LOJ&num;6066&rsqb;&period; 「2017 山东一轮集训 Day3」第二题&lbrack;二分&plus;括号序列&plus;hash&rsqb;

    题意 题目链接 分析 首先二分,假设二分的答案为 \(mid\),然后考虑利用括号序列来表示树的形态. 点 \(u\) 的 \(k-\) 子树的括号序列表示实际上是刨去了 \(u\) 子树内若干个与 ...

  10. POI 生成带联动下拉框的excel表格

    参考:https://www.cnblogs.com/cjbbk/p/7527276.html 解决POI3.17 与其它版本的不同的坑:https://blog.csdn.net/Weirdo_zh ...