- 模块:一个
.lua文件就是一个模块,通常把一组相关的函数、变量、数据封装在这个文件里,对外暴露指定接口; - 包:多个功能相关的模块组成的集合(比如放在同一个目录下),Lua 中包的管理主要靠目录结构和
package.path配置。
Lua 模块的本质是:把模块内的功能(函数、变量)挂载到一个 table 上,最后返回这个 table,让外部能访问到指定功能(未挂载的则为私有)。
定义模块
-- 定义模块内的私有函数(仅模块内可用,不导出)
local function check_num(num)
return type(num) == "number"
end
-- 定义模块的公开接口(挂载到 table 上)
local mymath = {}
-- 公开函数:加法
function mymath.add(a, b)
if not (check_num(a) and check_num(b)) then
error("参数必须是数字")
end
return a + b
end
-- 公开函数:乘法
function mymath.mul(a, b)
if not (check_num(a) and check_num(b)) then
error("参数必须是数字")
end
return a * b
end
-- 公开变量
mymath.PI = 3.1415926
-- 必须返回这个 table(核心!否则外部无法访问)
return mymath
加载模块
外部文件通过 require("模块名") 加载模块,这是 Lua 加载模块的核心方式,有几个关键特性:
- 模块名称不要和内置模块重名
- 如果有目录关系,require的时候以 . 分隔
-- 加载模块(模块名不带 .lua 后缀)
local mm = require("mymath")
-- 调用模块的公开函数
print(mm.add(3, 5)) -- 输出:8
print(mm.mul(4, 6)) -- 输出:24
print(mm.PI) -- 输出:3.1415926
-- 无法访问模块内的私有函数(check_num)
-- print(mm.check_num(5)) -- 报错:attempt to index field 'check_num' (a nil value)
模块查找路径
require 会根据 package.path 配置的路径查找模块文件,默认路径包含当前目录(./?.lua);
如果模块不在默认路径下,需要手动修改 package.path:
-- 查看当前模块查找路径
print(package.path)
-- 添加自定义路径(比如模块放在 lib 目录下)
package.path = package.path .. ";./lib/?.lua"
-- 加载 lib 目录下的模块
local utils = require("utils")
包的管理
当模块数量多的时候,需要按功能组织成 “包”(目录),核心是通过 init.lua 实现目录作为模块。
比如创建一个 utils 包,包含 string.lua 和 math.lua 两个模块:
project/
├── main.lua # 主程序
└── utils/ # 包目录
├── init.lua # 包的入口文件(关键)
├── string.lua # 字符串工具模块
└── math.lua # 数学工具模块
init.lua
-- utils/init.lua
local utils = {}
-- 加载子模块并挂载到 utils 上
utils.string = require("utils.string")
utils.math = require("utils.math")
-- 也可以导出常用函数到顶层
function utils.trim(str)
return utils.string.trim(str)
end
return utils
使用包
-- 加载 utils 包(实际加载 utils/init.lua)
local utils = require("utils")
-- 调用子模块的函数
print(utils.string.trim(" hello lua ")) -- 输出:hello lua
print(utils.math.square(5)) -- 输出:25
-- 调用顶层导出的函数
print(utils.trim(" test ")) -- 输出:test