Lua中require、dofile、loadfile的區別

ua文件是以chunk的方式存在的,其本質是一個函數
在lua中,加載代碼文件,通常會見到require、dofile、loadfile等函數,分析如下:

1、require
在加載一個.lua文件時,require會先在package.loaded中查找此模塊是否存在,如果存在,直接返回模塊。
如果不存在,則加載模塊文件。示例如下:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --test1.lua  
  2. function Fac(n)  
  3.     if n <= 1 then  
  4.         return n  
  5.     end  
  6.     return n * Fac(n-1)  
  7. end  
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --test2.lua  
  2. a = require("test1")  
  3. print("require res="..tostring(a))  
  4. print("5!="..Fac(5))  
運行test2.lua,結果如下:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. require res=true  
  2. 5!=120  
小結:require的特點是僅加載一次,並且對於模塊會按照特定的搜索規則去查找文件並加載。

2、dofile和loadfile
dofile:讀入代碼文件並編譯執行。每調用dofile一次,都會重新編譯執行一次。
loadfile:編譯代碼,將整個模塊文件當成一個函數返回,但是不執行代碼。
dofile是對loadfile的一次包裝
示例代碼:將test2.lua代碼修改成:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --test2.lua  
  2. a = loadfile("test1.lua")  
  3. print("loadfile res="..tostring(a))  
  4. print("5!="..Fac(5))  
結果:

這就說明,代碼確實沒有運行,而且loadfile是返回了一個函數
dofile測試如下:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --test2.lua  
  2. a = dofile("test1.lua")  
  3. print("dofile res="..tostring(a))  
  4. print("5!="..Fac(5))  
結果:


那麼,在lua中,如何利用這些函數,編寫一個模塊呢?
如果你只是需要編寫一個函數庫,比如所有對數據運算的操作,math_func.lua,可能的功能函數如下:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --math_func.lua  
  2.   
  3. function Sum(a, b)  
  4.     return a + b  
  5. end  
  6.   
  7. function Fac(n)  
  8.     if n <= 1 then  
  9.         return n  
  10.     end  
  11.     return n * Fac(n-1)  
  12. end  
如果是用dofile執行,那麼毫無疑問,Sum和Fac等函數,會執行到全局命名空間中,就像上面dofile的調用示例一樣。
這樣的做法是不提倡的,原因如下:
1:會引起命名混亂,a.lua裏面有個Sum,b.lua裏面也有個Sum,最後就會出現衝突了,函數會被覆蓋
2:調用方無法識別
所以,我比較喜歡的做法是:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --math_func.lua  
  2. math_func = {}  
  3.   
  4. function math_func.Sum(a, b)  
  5.     return a + b  
  6. end  
  7.   
  8. function math_func.Fac(n)  
  9.     if n <= 1 then  
  10.         return n  
  11.     end  
  12.     return n * math_func.Fac(n-1)  
  13. end  
  14.   
  15. return math_func  
調用示例:
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. --test.lua  
  2. MATH_FUNC = require("test1")  
  3. print("11 + 22 = "..tostring(MATH_FUNC.Sum(11,22)))  
  4. print("5!="..MATH_FUNC.Fac(5))  

避免了名字空間問題,也方便了不少,同時也不用擔心重複加載
發佈了19 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章