OpenResty 从入门到实战
温铭
OpenResty 软件基金会第一任主席,Apache APISIX 项目 VP
20903 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 52 讲
结束语 (1讲)
OpenResty 从入门到实战
15
15
1.0x
00:00/00:00
登录|注册

11 | 剖析Lua唯一的数据结构table和metatable特性

让 table 被调用
从元表中查询元素
__call
__index
获取 table 的元表
为一个 table 设置元表
重载__add__tostring等元方法
类似操作符重载
可替代table.getn
获取 table 长度的函数
避免反复创建和销毁 table 的开销
需要根据实际场景预设空间大小
预先分配数组和哈希的空间大小
尽量避免在热代码中使用
时间复杂度为O(n)
按下标拼接数组部分的元素
删除哈希部分的元素需将对应的value设置为nil
只能删除数组部分的元素
在OpenResty环境下应避免使用
O(n)时间复杂度
下节课继续学习其他常用函数
table 和 metatable 在 OpenResty 的库中大量使用
:.的等价性
使用元表模拟类和类方法
元方法
getmetatable(table)
setmetatable(table, metatable)
元表的作用
table.nkeys
table.clear() 清空 table
table.new(narray, nhash) 新建 table
table.insert 插入一个元素
table.concat 元素拼接函数
table.remove 删除指定元素
table.getn 获取元素个数
通过ipairs函数遍历数组部分的内容
包含数组和哈希
总结
面向对象
元表
OpenResty 的 table 扩展函数
LuaJIT 的 table 扩展函数
table 库函数
LuaJIT 中唯一的数据结构:table
剖析Lua唯一的数据结构table和metatable特性

该思维导图由 AI 生成,仅供参考

你好,我是温铭。今天我们一起学习下 LuaJIT 中唯一的数据结构:table
和其他具有丰富数据结构的脚本语言不同,LuaJIT 中只有 table 这一个数据结构,并没有区分开数组、哈希、集合等概念,而是揉在了一起。让我们先温习下之前提到过的一个例子:
local color = {first = "red", "blue", third = "green", "yellow"}
print(color["first"]) --> output: red
print(color[1]) --> output: blue
print(color["third"]) --> output: green
print(color[2]) --> output: yellow
print(color[3]) --> output: nil
这个例子中, color 这个 table 包含了数组和哈希,并且可以互不干扰地进行访问。比如,你可以用 ipairs 函数,只遍历数组部分的内容:
$ resty -e 'local color = {first = "red", "blue", third = "green", "yellow"}
for k, v in ipairs(color) do
print(k)
end
'
table 的操作是如此重要,以至于 LuaJIT 对标准 Lua 5.1 的 table 库做了扩展,而 OpenResty 又对 LuaJIT 的 table 库做了更进一步的扩展。下面,我们就一起来分别看下这些库函数。

table 库函数

先来看标准 table 库函数。Lua 5.1 中自带的 table 库函数并不多,我们可以大概浏览一遍。

table.getn 获取元素个数

我们在 标准 Lua 和 LuaJIT 章节中曾经提到过,想正确地获取到 table 所有元素的个数,在 LuaJIT 中是一个老大难问题。
对于序列,你用table.getn 或者一元操作符 # ,就可以正确返回元素的个数。比如下面这个例子,就会返回我们预期中的 3。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

LuaJIT中的`table`是唯一的数据结构,融合了数组和哈希的特性,没有区分开数组、哈希、集合等概念。文章介绍了LuaJIT中`table`的操作和扩展函数,包括标准table库函数和LuaJIT扩展的函数。其中,`table.new`用于新建table并预先分配数组和哈希的空间大小,而`table.clear`用于清空table里的所有数据。此外,文章还介绍了元表的概念和作用,以及如何使用元表来实现面向对象编程。通过元表,可以重载操作符、定义转换为字符串的函数,以及模拟类和类方法。这些内容对于读者快速了解LuaJIT中table和metatable的特性具有很好的指导意义。文章内容深入浅出,涵盖了LuaJIT中table和metatable的基本概念和高级应用,对于读者理解和应用LuaJIT具有很好的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OpenResty 从入门到实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(18)

  • 最新
  • 精选
  • 直接 lua 运行 table.getn 会报这样的错的 lua: table.lua:7: attempt to call a nil value (field 'getn') 我查了一下, lua5.1 之后把这方法去掉了,那么为什么 luajit 和 openresty 不把这个方法废弃呢?还保留呢?

    作者回复: 因为 LuaJIT 是基于 Lua 5.1的语法来实现的,并没有跟随Lua 5.2 和 5.3

    2019-06-19
    4
  • 小飞哥 ‍超級會員
    localhost: ~/geektime/lua $ resty -e 'local color = {first = "red", "blue", third = "green", "yellow"} > color.first = nil > for k, v in pairs(color) do > print(v) > end' blue yellow green localhost: ~/geektime/lua $ resty -e 'local color = {first = "red", "blue", third = "green", "yellow"} > table.remove(color, 1) > for k, v in pairs(color) do > print(v) > end' yellow green red 看结果为什么打印一个是正序,一个是倒序呢?

    作者回复: 字典的顺序是不保证的,大部分语言都是如何

    2019-06-22
    2
  • John
    老师,能否专门讲解一下lua面向对象是如何实现继承,抽象类的,我看了orange的源码发现不太容易理解,源码如下: -- local BasePlugin = Object:extend() function Object:extend() local cls = {} for k, v in pairs(self) do if k:find("__") == 1 then cls[k] = v end end cls.__index = cls cls.super = self setmetatable(cls, self) return cls end function Object:implement(...) for _, cls in pairs({...}) do for k, v in pairs(cls) do if self[k] == nil and type(v) == "function" then self[k] = v end end end end

    作者回复: 不推荐用 Lua 的 table 来模拟实现继承等这种复杂的功能,就像你说的一样,可读性太差,一般人的脑子都转不过来。。。

    2019-06-20
    3
    1
  • helloworld
    函数不可貌相,海水不可(斗量) :)

    作者回复: :)感谢 fix typo

    2019-06-19
    1
  • 在luajit 扩展的table 函数中 local new_tab = require('table.new') 或者 require('table.clear') 用 luajit 去执行 都会报错找不动 moudule的错误的 luajit: table_luajit.lua:1: module 'table.new' not found: luajit 的版本 2.0.5

    作者回复: 需要 LuaJIT 2.1 的版本才行, 文档在这里:https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218

    2019-06-19
    2
    1
  • 英雄
    是重载还是重写?java里面的重载是:指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同 方法重写是:存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型

    作者回复: 按照你的定义就是重写。Lua 没有类的概念,是模拟出来的,所以做不到重载这么高级。

    2019-07-11
  • ArtEngr
    “另外,超出预设的空间大小,也可以正常使用,只不过性能会退化” 很多时候与外界交互数据,无法准确知道table大小。

    作者回复: 可以设置大一些,留一些缓存

    2019-06-21
  • wusiration
    lua-resty-mysql 模拟OO,个人理解是便于复用mysql连接,无需反复开启mysql连接;麻烦老师解惑一下
    2019-07-01
    9
  • 石头Rocky
    setmetatable({ sock = sock }, mt) 构造函数返回的table是{ sock = sock }这个表。 当调用方使用 set_timeout方法时,在表内找不到set_timeout方法,便会去__index所指的_M中去寻找。
    2019-06-19
    7
  • Triple Z 💤
    `table.nkeys` 和 `table.getn` / `#` 有什么样的性能差异吗?我查了下 NYI 列表,貌似 `getn` 一样可以被 JIT。从实现上来看,貌似 `nkeys` 也是 O(n)。
    2022-12-16归属地:广东
    1
收起评论
显示
设置
留言
18
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部