require关键字
lua中使用require来加载对应的模块。
基本用法:
比如我有个一个文件test.lua,内容如下:
test = {}
test.fun1 = function() return 1 end
return test;
然后在main.lua中使用require引入:
require('test')
print(test.fun1()) --> 1
加载过程
跟node加载模块一样,lua中的模块加载过程也需要一个查找过程。在使用require加载lua模块的时候,lua首先会查看package.loaded表中是否存在该模块,如果存在,说明该模块之前已经加载过了,那么久直接返回这个表中的对应模块。
其实就是模块的全局缓存的效果,保证每个模块只需加载一次就够了。
如果package.loaded表中没有该模块,则会先针对这个模块寻找一个loader,这个loader工作你懂得,就是用来加载这个模块的。
所以现在的流程就是,
-
- require(moduleName)
-
- 看下package.loaded[moduleName]有没有值,没有走第三步
-
- 看下package.preload[moduleName]有没有值,有就返回,没有走第四步
-
- 使用packege.path中指定的路径去搜索loader,如果失败走第五步
-
- 使用packge.cpath中指定的路径去搜索C loader,如果还是失败了,则走第六步
-
- 使用package.searchers中配置的loader来加载模块。
如果以上的流程中查找到了模块的loader,则require会调用这个加载程序,并且将模块名称和一个额外的参数传递给该loader(如果这个loader来自一个文件,则该参数的值为文件名)。如果loader没有给package.loaded添加任何值而且也没有返回任何的非零值,则讲package.loaded[moduleName]设置为true。然后require会返回package.loaded[moduleName]给到调用方。
在上面的加载过程中,如果出现了失败或者错误,require就会抛出一个错误。
package.preload
用来存储一些特殊的模块,我的理解就是用来存储一些自定义的loader的。
package.path
这个配置用来告诉lua去哪里查找模块的loader。 在启动时,Lua使用环境变量LUA_PATH_5_3或环境变量LUA_PATH的值或使用luaconf.h中定义的默认路径初始化此变量(如果未定义这些环境变量)。任何 ”;;”在环境变量的值中由默认路径替换。
package.cpath
跟path差不多,主要用来加载C语言的库,这个就不说了。
package.searchers
package.searchers是lua用来控制如何加载以及去哪里加载对应模块的表。这个表里面的每一个属性都是一个查找函数,lua会按升序排序,然后根据这个顺序来调用查找函数,将require函数传递过来的参数给到查找函数,然后去执行对应的查找。
lua在初始化package.searchers表的时候,会添加以下4个查找函数:
-
- 第一个查找函数只在package.preload表中查找loader
-
- 第二个查找函数,按package.path中的配置路径来查找loader,匹配过程用package.searchpath中的配置说明来匹配
-
- 第三个是加载C语言库的,跟path的一样
-
- 第四个也是用来加载C语言库的,就不说了,有需要的查看这里的官方文档
package.searchpath
package.searchpath (name, path [, sep [, rep]])
- name: 搜索的名称
- path: 指定的搜索路径
- sep:名称中的分隔符,默认是一个点(.)
- rep: 在路径中的占位符,最终会被实际的名称给替换,默认为?
举个例子: 如果path中配置了下面这个路径:
"./?.lua;./?.lc;/usr/local/?/init.lua"
然后需要查找一个foo.a模块的话,则会去寻找这些路径的文件:
./foo/a.lua
./foo/a.lc
/usr/local/foo/a/init.lua
返回第一个查找的结果,如果没有找到,则返回nil和错误信息(尝试打开的所有文件)。