OpenResty Lua 抵制使用 module() 定義模塊

2021-08-12 16:38 更新

舊式的模塊定義方式是通過 ?module("filename"[,package.seeall])*? 來顯式聲明一個包,現(xiàn)在官方不推薦再使用這種方式。這種方式將會返回一個由 ?filename ?模塊函數(shù)組成的 ?table?,并且還會定義一個包含該 table 的全局變量。

?module("filename", package.seeall)?這種寫法是不提倡的,官方給出了兩點原因:

  1. ?package.seeall? 這種方式破壞了模塊的高內(nèi)聚,原本引入 "filename" 模塊只想調(diào)用它的 foobar() 函數(shù),但是它卻可以讀寫全局屬性,例如 ?"filename.os"?。
  2. ?module ?函數(shù)壓棧操作引發(fā)的副作用,污染了全局環(huán)境變量。例如 ?module("filename")? 會創(chuàng)建一個 ?filename ?的 ?table?,并將這個 ?table ?注入全局環(huán)境變量中,這樣使得沒有引用它的文件也能調(diào)用 ?filename ?模塊的方法。

比較推薦的模塊定義方法是:

-- square.lua 長方形模塊
local _M = {}           -- 局部的變量
_M._VERSION = '1.0'     -- 模塊版本

local mt = { __index = _M }

function _M.new(self, width, height)
    return setmetatable({ width=width, height=height }, mt)
end

function _M.get_square(self)
    return self.width * self.height
end

function _M.get_circumference(self)
    return (self.width + self.height) * 2
end

return _M
引用示例代碼:
local square = require "square"

local s1 = square:new(1, 2)
print(s1:get_square())          --output: 2
print(s1:get_circumference())   --output: 6

另一個跟 Lua 的 module 模塊相關(guān)需要注意的點是,當(dāng) lua_code_cache on 開啟時,require 加載的模塊是會被緩存下來的,這樣我們的模塊就會以最高效的方式運行,直到被顯式地調(diào)用如下語句(這里有點像模塊卸載):

package.loaded["square"] = nil

我們可以利用這個特性代碼來做一些高階玩法,比如代碼熱更新等。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號