require

用法不赘述,加载过程

  • 查找package.loaded 确认目标模块是否加载过
  • 没加载过,则通过package.loaders 获取loader
  • 通过loader去加载目标模块

tip:

  • “ . ” 在require时会被替换为文件系统的分隔符,比如/,所以脚本所在的文件夹命名不能包含”.”
  • 加载一个lua文件时,整个lua文件会被当做一个代码块,然后执行,并且接收require(name)的参数name作为参数
文件test.lua  
require("test2")

文件test2.lua
print(...)

运行test.lua,会输出 "test2"

package.loaders

控制require如何加载一个module的表

表内的值是一个搜索函数,调用require时,会升序地调用所有搜索函数;

搜索函数找到module时会返回加载module的function,反之返回errstr or nil

搜索函数顺序:

  1. 从package.preload里查找 应用:可以在preload修改目标模块的加载方式。
  2. 从package.path(搜索路径)里找 ,热更新的原理就是通过设置搜索路径的优先级来实现的,优先加载update文件夹下的lua代码。如何设置呢?应该是按添加顺序吧(没试过)
  3. 从 package.cpath里找
    例如: 在package.cpath = “./?.so;./?.dll;/usr/local/?/init.so” 中查找foo
    查找顺序: ./foo.so, ./foo.dll, and /usr/local/foo/init.so
    找到后,会链接该库,并且在该库中调用入口函数,入口函数是luaopen_[moduleName],moduleName(此时是foo):
- 如果moduleName包含".",那么入口函数则是用"_"代替,如foo.b 对应luaopen_foo_b。在导出C库给lua时,入口函数就是这么来的。
- 如果包含"-",那么入口函数会抛弃前缀,如a-foo对应luaopen_foo。

4.
The fourth searcher tries an all-in-one loader. It searches the C path for a library for the root name of the given module. For instance, when requiring a.b.c, it will search for a C library for a. If found, it looks into it for an open function for the submodule; in our example, that would be luaopen_a_b_c. With this facility, a package can pack several C submodules into one single library, with each submodule keeping its original open function.

module

Creates a module.这个功能在5.2版本的lua中已经被去掉了。平时使用的情况也比较少。
具体细节可以参考云风的博客:
https://blog.codingnow.com/2018/04/lua_54_nil_in_table.html

module(name[,…])

1.如果package.loaded[name] 存在,则模块为这个

2.全局表中某个table名字是name,那这个表为module

3.都没有则创建一个新table:name,且package.loaded[name]也会被赋值为该表

4.module会把当前的表设置为当前函数的env;

5.如果name包含”.”,如”a.b”,那么会创建一个全局表a= {b={}},但是此时由于第4条,所有全局表在module之后的语句内都无法再访问之前的全局变量;
(想访问必须这样写module(“a.b”,package.seeall))

local print=print
local _G = _G
module("a.b",package.seeall)--如果没有package.seeall,name下面的getfenv会报错,因为找不到;
print(getfenv())
print(_G.a.b)    
两个是相同的,