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

12 | 高手秘诀:识别Lua的独有概念和坑

变量的个数限制
json编码时无法区分array和dict
正则模式匹配
下标从0开始还是从1开始
upvalue的应用
upvalue的概念
闭包的基础
Lua中的闭包
弱表的应用
设置弱表的方式
弱表的作用
Lua中的垃圾回收
常见的坑
闭包和upvalue
弱表
高手秘诀:识别Lua的独有概念和坑
参考文章

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

你好,我是温铭。
上一节中,我们一起了解了 LuaJIT 中 table 相关的库函数。除了这些常用的函数外,今天我再为你介绍一些 Lua 独有的或不太常用的概念,以及 OpenResty 中常见的 Lua 的坑。

弱表

首先是 弱表(weak table),它是 Lua 中很独特的一个概念,和垃圾回收相关。和其他高级语言一样,Lua 是自动垃圾回收的,你不用关心具体的实现,也不用显式 GC。没有被引用到的空间,会被垃圾收集器自动完成回收。
但简单的引用计数还不太够用,有时候我们需要一种更灵活的机制。举个例子,我们把一个 Lua 的对象 Foo(table 或者函数)插入到 table tb 中,这就会产生对这个对象 Foo 的引用。即使没有其他地方引用 Footb 对它的引用也还一直存在,那么 GC 就没有办法回收 Foo 所占用的内存。这时候,我们就只有两种选择:
一是手工释放 Foo
二是让它常驻内存。
比如下面这段代码:
$ resty -e 'local tb = {}
tb[1] = {red}
tb[2] = function() print("func") end
print(#tb) -- 2
collectgarbage()
print(#tb) -- 2
table.remove(tb, 1)
print(#tb) -- 1
不过,你肯定不希望,内存一直被用不到的对象占用着吧,特别是 LuaJIT 中还有 2G 内存的上限。而手工释放的时机并不好把握,也会增加代码的复杂度。
那么这时候,就轮到弱表来大显身手了。看它的名字,弱表,首先它是一个表,然后这个表里面的所有元素都是弱引用。概念总是抽象的,让我们先来看一段稍加修改后的代码:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了Lua中的一些独特概念和常见坑,以及在OpenResty开发中遇到的Lua相关问题。其中包括弱表、闭包和upvalue的概念,以及在实际开发中需要注意的问题。弱表在解决垃圾回收中的引用问题方面具有独特作用,而闭包和upvalue则是Lua中重要的概念,能够帮助访问另一个函数词法作用域中的变量。此外,文章还提到了在OpenResty开发中常见的坑,如Lua中下标从1开始,但在LuaJIT中使用ffi.new创建的数组下标却是从0开始。另外,文章还介绍了Lua中的正则模式匹配和json编码时无法区分array和dict的问题,以及对变量个数限制的讨论。总的来说,本文通过介绍这些内容,帮助读者更好地理解Lua的特点和注意事项,为读者快速了解Lua的独特概念和在实际开发中需要注意的问题提供了有益的指导。

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

全部留言(19)

  • 最新
  • 精选
  • 燕羽阳
    lua指令是32位,其中6位作为操作码,8位作为本地变量和upvalue寻址(即256个)。类似的限制还有函数中只能定义262144个常量(2^18)

    作者回复: 👍 这些设计到 Lua 虚拟机指令,感兴趣的同学推荐看看张秀宏老师写的《自己动手实现Lua:虚拟机、编译器和标准库》

    2019-07-01
    2
    13
  • 小飞哥 ‍超級會員
    写在最后的do end 是不是表示代码块的意思? do end封装后是不是其它function是无法访问的?

    作者回复: 是的,除非你在 do end 之前预定义了一个变量,比如: local f do function f() ... end end -- do

    2019-06-22
    2
  • helloworld
    老师,文中提到的OpenResty的API和LuaJIT的API,你看我这么理解对不对: OpenResty的API,是指lua-nginx-module模块提供的API LuaJIT的API,是指lua-resty-core和各种lua-resty-*项目中提供的API

    作者回复: OpenResty 的 API 指的是lua-nginx-module和lua-resty-core提供的接口,都是 `ngx` 来头的;LuaJIT 的 API 是扩展了 Lua 内置的库,比如 `table.new` 这种

    2019-06-21
    2
    2
  • 罐头瓶子
    upvalue 上线250这个是考虑到变量查找效率的问题?如果local变量过多可以放在table里面加快查找效率?

    作者回复: 其实上限是 256, 这个是 Lua 虚拟机的指令占用的大小决定的。超过 256 的话,Lua 虚拟机就不支持了。

    2019-06-21
    1
  • 英雄
    local t = cjson.empty_array 这行代码没看懂

    作者回复: 这是把 cjson 这个模块的 empty_array 函数,赋值给了 t 这个变量。在 Lua 中函数是一等公民,可以像变量一样使用

    2019-07-11
  • geraltlaush
    coroutine 0: /usr/local/openresty/nginx/lua/hello.lua: in main chunk, client: 127.0.0.1, server: localhost, request: "GET /lua HTTP/1.1", host: "localhost" 2019/07/09 14:21:09 [error] 854136#854136: *16 lua entry thread aborted: runtime error: /usr/local/openresty/nginx/lua/hello.lua:17: attempt to index global 'cjson' (a nil v stack traceback,老师,这个是怎么回事

    作者回复: 能否贴下具体的代码?给个 github 的 gist 地址就行

    2019-07-09
  • HelloBug
    老师,typo:”即使这个变量并不在 foo 里面定义“,应该是”即使这个变量并不在 bar 里面定义“~~

    作者回复: 多谢反馈,已经修改:)

    2019-06-26
  • soooldier
    看完后对week table还是完全懵的,有没有更浅显易懂的文章呢?

    作者回复: 可以看 Lua 作者写的那本书,就是《Lua 程序设计》,里面专门有讲 weak table

    2019-06-24
  • HelloBug
    为什么table的下标是数字时,设置弱表属性是key,不会对其进行垃圾回收,而是table和function时会对其进行垃圾回收?
    2019-06-26
    1
    2
  • HelloBug
    开篇讲解弱表的例子中,如果table中有对Foo的引用,不是说明Foo占用的内存是有用的吗?为什么要释放Foo占用的内存?什么时候会对其进行了引用,反倒希望设置弱表属性,希望GC对其进行垃圾回收呢?
    2019-06-26
    2
收起评论
显示
设置
留言
19
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部