# 13 Lua 模塊與包
模塊類似于一個封裝庫,從 Lua 5.1 開始,Lua 加入了標準的模塊管理機制,可以把一些公用的代碼放在一個文件里,以 API 接口的形式在其他地方調用,有利于代碼的重用和降低代碼耦合度。
Lua 的模塊是由變量、函數等已知元素組成的 table,因此創建一個模塊很簡單,就是創建一個 table,然后把需要導出的常量、函數放入其中,最后返回這個 table 就行。以下為創建自定義模塊 module.lua,文件代碼格式如下:
```lua
-- 文件名為 module.lua
-- 定義一個名為 module 的模塊
module = {}
-- 定義一個常量
module.constant = "這是一個常量"
-- 定義一個函數
function module.func1()
io.write("這是一個公有函數!\n")
end
local function func2()
print("這是一個私有函數!")
end
function module.func3()
func2()
end
return module
```
由上可知,模塊的結構就是一個 table 的結構,因此可以像操作調用 table 里的元素那樣來操作調用模塊里的常量或函數。
上面的 func2 聲明為程序塊的局部變量,即表示一個私有函數,因此是不能從外部訪問模塊里的這個私有函數,必須通過模塊里的公有函數來調用.
---
## require 函數
Lua提供了一個名為require的函數用來加載模塊。要加載一個模塊,只需要簡單地調用就可以了。例如:
```lua
require("<模塊名>")
```
或者
```lua
require "<模塊名>"
```
執行 require 后會返回一個由模塊常量或函數組成的 table,并且還會定義一個包含該 table 的全局變量。
```lua
-- test_module.lua 文件
-- module 模塊為上文提到到 module.lua
require("module")
print(module.constant)
module.func3()
```
以上代碼執行結果為:
```lua
這是一個常量
這是一個私有函數!
```
或者給加載的模塊定義一個別名變量,方便調用:
```lua
-- test_module2.lua 文件
-- module 模塊為上文提到到 module.lua
-- 別名變量 m
local m = require("module")
print(m.constant)
m.func3()
```
以上代碼執行結果為:
```lua
這是一個常量
這是一個私有函數!
```
---
### 加載機制
對于自定義的模塊,模塊文件不是放在哪個文件目錄都行,函數 require 有它自己的文件路徑加載策略,它會嘗試從 Lua 文件或 C 程序庫中加載模塊。
require 用于搜索 Lua 文件的路徑是存放在全局變量 **package.path **中,當 Lua 啟動后,會以環境變量 **LUA\_PATH** 的值來初始這個環境變量。如果沒有找到該環境變量,則使用一個編譯時定義的默認路徑來初始化。
當然,如果沒有 LUA\_PATH 這個環境變量,也可以自定義設置,在當前用戶根目錄下打開 .profile 文件(沒有則創建,打開 .bashrc 文件也可以),例如把 "~/lua/" 路徑加入 LUA\_PATH 環境變量里:
```bash
#LUA_PATH
export LUA_PATH="~/lua/?.lua;;"
```
文件路徑以 ";" 號分隔,最后的 2 個 ";;" 表示新加的路徑后面加上原來的默認路徑。
接著,更新環境變量參數,使之立即生效。
```bash
source ~/.profile
```
這時假設 package.path 的值是:
```lua
/Users/dengjoe/lua/?.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;
/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua
```
那么調用 require\("module"\) 時就會嘗試打開以下文件目錄去搜索目標。
```lua
/Users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/5.1/module.lua
/usr/local/share/lua/5.1/module/init.lua
/usr/local/lib/lua/5.1/module.lua
/usr/local/lib/lua/5.1/module/init.lua
```
如果找過目標文件,則會調用 package.loadfile 來加載模塊。否則,就會去找 C 程序庫。
搜索的文件路徑是從全局變量 package.cpath 獲取,而這個變量則是通過環境變量 LUA\_CPATH 來初始。
搜索的策略跟上面的一樣,只不過現在換成搜索的是 so 或 dll 類型的文件。如果找得到,那么 require 就會通過 package.loadlib 來加載它。
---
##
- 1 Lua介紹及環境
- 2 基本語法
- 3 數據類型
- 4 Lua 變量
- 5 循環
- 6 流程控制
- 7 函數
- 8 運算符
- 9 字符串
- 10 數組
- 11 迭代器
- 12 table
- 13 Lua 模塊與包
- 14 Lua 元表(Metatable)
- 14.1 元表案例
- 15 Lua 協同程序(coroutine)
- 16 Lua 文件IO
- 17 Lua 面向對象
- 17.1 類
- 17.2 繼承
- 17.3 封裝
- 18 Lua 與 Mysql
- 19 Lua 與 redis
- 20 Lua 與 JSON
- 21 Lua 與 http
- 22 Lua 與 Nginx
- 22.1 Nginx_Lua的安裝及環境
- 22.2 ngx_lua API(全表)
- 22.3 常用命令介紹
- 22 Lua 人工智能
- (1) Torch的安裝
- (2)Tensor
- Lua與C混合編程