Lua 模块的基本概念
Lua 中的模块是一个由函数、变量组成的代码库,通常保存在独立的 .lua
文件中。模块通过 return
语句导出其内容,供其他脚本调用。模块化设计可以提高代码复用性,便于管理。
创建模块
模块通常以 .lua
文件形式存在,文件内通过 return
返回一个表(table),表中包含模块的公开函数或变量。例如:
-- 文件名为 mymodule.lua
local M = {} -- 模块表function M.add(a, b)return a + b
endfunction M.sub(a, b)return a - b
endreturn M -- 导出模块
加载模块
Lua 5.1 及以上版本使用 require
函数加载模块。require
会搜索模块路径并执行文件,返回模块导出的内容:
local mymodule = require("mymodule") -- 加载模块
print(mymodule.add(1, 2)) -- 调用模块函数
模块搜索路径
require
通过 package.path
和 package.cpath
确定搜索路径。package.path
用于 .lua
文件,package.cpath
用于二进制模块(如 .dll
或 .so
)。默认路径包含当前目录和 Lua 安装路径。
print(package.path) -- 查看 Lua 模块搜索路径
print(package.cpath) -- 查看二进制模块搜索路径
模块的局部变量
模块中未暴露的局部变量对外不可见,实现封装:
local M = {}
local privateVar = 100 -- 局部变量,外部不可访问function M.getPrivate()return privateVar
endreturn M
包管理工具
Lua 的包管理工具如 LuaRocks 可以安装和管理第三方模块。安装命令示例:
luarocks install luasocket
模块的缓存机制
require
会缓存已加载的模块,避免重复加载。可以通过 package.loaded
查看或清除缓存:
package.loaded["mymodule"] = nil -- 清除模块缓存
require("mymodule") -- 重新加载
使用环境隔离
模块可以通过设置 _ENV
实现沙盒环境,避免污染全局命名空间:
local M = {}
setmetatable(M, { __index = _G }) -- 继承全局环境
_ENV = M -- 切换环境function add(a, b)return a + b
endreturn M
模块的依赖管理
模块可以依赖其他模块,通过 require
引入:
local json = require("dkjson") -- 引入第三方 JSON 模块
local M = {}function M.toJson(t)return json.encode(t)
endreturn M
动态加载模块
loadfile
或 dofile
可以动态加载模块,但不推荐替代 require
:
local chunk = loadfile("mymodule.lua") -- 加载但不执行
local M = chunk() -- 执行并获取模块
模块的命名规范
Lua 模块通常使用小写字母和下划线命名,如 my_module.lua
。避免与 Lua 关键字冲突。
模块的版本控制
在模块中定义版本号,便于管理:
local M = {}
M._VERSION = "1.0.0"
return M
模块的测试与调试
模块可以通过独立的测试脚本验证功能:
local mymodule = require("mymodule")
assert(mymodule.add(1, 2) == 3)
Lua 5.2 后的模块变化
Lua 5.2 移除了 module
函数,推荐直接使用 return table
的方式定义模块。
模块的打包与分发
将模块打包为 .rocks
文件或直接发布源码,便于其他开发者使用。LuaRocks 支持模块发布:
luarocks pack mymodule
模块的跨平台兼容性
确保模块代码兼容不同操作系统,避免路径硬编码:
local path_sep = package.config:sub(1,1) -- 获取系统路径分隔符
local path = "foo" .. path_sep .. "bar.lua"
模块的元表应用
通过元表为模块添加默认方法或重载操作符:
local M = {}
setmetatable(M, {__add = function(a, b) return a.value + b.value end
})
M.value = 10
return M