当前位置: 首页 > news >正文

Lua中的require与package.loaded

require (modname)

加载一个模块。 这个函数首先查找 package.loaded 表, 检测 modname 是否被加载过。 如果被加载过,require 返回 package.loaded[modname] 中保存的值。 否则,它试着为模块寻找 加载器 。
require 遵循 package.searchers 序列的指引来查找加载器。 如果改变这个序列,我们可以改变 require 如何查找一个模块。 下列说明基于 package.searchers 的默认配置。
首先 require 查找 package.preload[modname] 。 如果这里有一个值,这个值(必须是一个函数)就是那个加载器。 否则 require 使用 Lua 加载器去查找 package.path 的路径。 如果查找失败,接着使用 C 加载器去查找 package.cpath 的路径。 如果都失败了,再尝试 一体化 加载器 (参见 package.searchers)。
每次找到一个加载器,require 都用两个参数调用加载器: modname 和一个在获取加载器过程中得到的参数。 (如果通过查找文件得到的加载器,这个额外参数是文件名。) 如果加载器返回非空值, require 将这个值赋给 package.loaded[modname]。 如果加载器没能返回一个非空值用于赋给 package.loaded[modname], require 会在那里设入 true 。 无论是什么情况,require 都会返回 package.loaded[modname] 的最终值。
如果在加载或运行模块时有错误, 或是无法为模块找到加载器, require 都会抛出错误。

package.loaded

用于 require 控制哪些模块已经被加载的表。 当你请求一个 modname 模块,且 package.loaded[modname] 不为假时, require 简单返回储存在内的值。
这个变量仅仅是对真正那张表的引用; 改变这个值并不会改变 require 使用的表。

简而言之就是:
在Lua中使用require进行模块的加载,被成功加载的模块会将这个模块的引用保存到package.loaded表中;在使用require进行模块加载的时候,会首先在package.loaded表中查找,检测这个模块是否被加载过,如果被加载过则返回这个模块在package.loaded中保存的值,否则加载这个模块!

那么问题来了,如果现在我需要重新加载一个已被成功加载过的模块呢?

例如:在进行更新之前就已经require过某一个模块,恰好本次的更新内容中就包含了这个模块的更新,在更新完成之后这个模块的内容发生了改变,但是由于在更新之前就已经require过了,package.loaded表中保存的这个模块的引用还是旧的,重新require无效!

其实解决办法很简单:在重新require之前将这个模块在package.loaded中保存的引用置空即可!

Test Demo
testRequire.lua

local testRequire = {name = "fightsyj"}

function testRequire:getName()
	return self.name
end

function testRequire:setName(name)
	self.name = name
end

return testRequire

test.lua

local modname = "testRequire"
local testRequire = require(modname)
print("------------------------------")
print(testRequire:getName())

delayDoSomething(function()
	testRequire = require(modname)  -- 在文件动态改变之后,重新require返回的依旧是原来就文件内容的引用
	print("------------------------------")
	print(testRequire:getName())

	package.loaded[modname] = nil  -- 将package.loaded表中保存的目标引用置空
	testRequire = require(modname)  -- 重新require这个模块
	print("------------------------------")
	print(testRequire:getName())
end, 5)  -- 延时5s,在这5s之内将testRequire.lua中的{name = "fightsyj"}改为{name = "fightsyj2"}

--[[ 
------------------------------
fightsyj
------------------------------
fightsyj
------------------------------
fightsyj2
]]

ps
delayDoSomething

参考:
Lua 5.3 参考手册

相关文章:

  • 配置文件多个一个符号,导致struts抛出了匪夷所思的错误
  • 签名不对,请检查签名是否与开发平台上填写的一致
  • win终端工具Cmder的配置与使用
  • hibernate的lazy配置引起的问题
  • Lua实战之table.remove
  • 老婆说明书
  • cocos2d-lua:改变子节点优先级reorderChild
  • 几天工作中的三个技巧!
  • cocos2d-lua:动作Actions的使用
  • Lua实战之判断连续
  • Lua实战之统计字符串中任意字符出现的次数
  • 用OE收GMAIL信
  • cocos2d-lua:进度条ProgressTimer的使用
  • 用HFNetChk下载更新补丁
  • cocos2d-lua:Label的使用
  • emacs初体验
  • ES6 学习笔记(一)let,const和解构赋值
  • JSONP原理
  • laravel5.5 视图共享数据
  • SOFAMosn配置模型
  • SpiderData 2019年2月23日 DApp数据排行榜
  • spring boot 整合mybatis 无法输出sql的问题
  • 从重复到重用
  • 记录:CentOS7.2配置LNMP环境记录
  • 人脸识别最新开发经验demo
  • 如何编写一个可升级的智能合约
  • 如何学习JavaEE,项目又该如何做?
  • 三分钟教你同步 Visual Studio Code 设置
  • PostgreSQL之连接数修改
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • (06)金属布线——为半导体注入生命的连接
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (zhuan) 一些RL的文献(及笔记)
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (南京观海微电子)——COF介绍
  • (小白学Java)Java简介和基本配置
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .Mobi域名介绍
  • .NET Framework 4.6.2改进了WPF和安全性
  • .NET编程C#线程之旅:十种开启线程的方式以及各自使用场景和优缺点
  • .net打印*三角形
  • .NET开源快速、强大、免费的电子表格组件
  • .Net语言中的StringBuilder:入门到精通
  • [100天算法】-二叉树剪枝(day 48)
  • [4.9福建四校联考]
  • [Android] Binder 里的 Service 和 Interface 分别是什么
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标
  • [C#]C# winform部署yolov8目标检测的openvino模型