最近准备开始写个系列分类叫五分钟技术分享,就是单章内容控制在五分钟适合碎片化的时间浏览。本期分享的主题是Lua语言中Require的工作原理
从 package.path 拼接当前require的路径进行查找,会从输出结果中挨个访问是否存在该文件,如果有就会通过loader(加载器)加载。
print(package.path) --Windows测试环境
--;.\?.lua;C:\Program Files (x86)\Lua\5.1\lua\?.lua;C:\Program Files (x86)\Lua\5.1\lua\?\init.lua;C:\Program Files (x86)\Lua\5.1\?.lua;C:\Program Files (x86)\Lua\5.1\?\init.lua;C:\Program Files (x86)\Lua\5.1\lua\?.luac
将上面的?替换为文件名,就是尝试加载的文件地址,多个分号分隔代表会从多个路径进行优先级查找。
require的模块都存储在package.loaded。
require "main"
for k, v in pairs(package.loaded) do
print("loaded:" .. k .. "")
end
-- loaded:string
-- loaded:debug
-- loaded:package
-- loaded:_G
-- loaded:io
-- loaded:os
-- loaded:table
-- loaded:math
-- loaded:coroutine
-- loaded:main 这边出现了main文件名
观察下面代码我们定义一个main.lua文件
main = {}
print("load file main")
return main --缺省情况下默认return true
运行下面的代码会得到输出:
local ma1 = require "main"
print(ma1)
local ma2 = require "main"
print(ma2)
-- load file main
-- table: 00EA98E8
-- table: 00EA98E8
可以看到 “load file main” 并不是每次被require的时候都会执行。只有在首次执行会输出。
默认没有return的情况下会走一个return true,lua会自己确保当前文件中执行函数只走一次就被缓存。 在显式添加return false的情况下,才会多次require每次都刷新package.loaded缓存过的数据。
main = {}
print("load file main")
return false
在调用的文件中:
require "main"
require "main"
输出:
load file main
load file main
还有另外一种方式就是将package.loaded.main设置为nil,require的时候会发现loaded中存储的main找不到了,就会再次走加载流程。
main = {}
print("load file main")
return main
在调用的文件中:
require "main"
package.loaded.main = nil
require "main"
输出:
load file main
load file main