學習 Lua 的必要性
- nginx開發
- apisix,kong插件開發
語言特點
- 語句結束沒有分號
- 跟 JavaScript 很像
- 默認定義的是全局變量,定義局部變量需要加 local 關鍵字
- 數組索引從1開始
- 沒有 i++ 操作符號,只能 i = i + 1
註釋
- 單行註釋
-- 註釋內容
- 多行註釋
--[[
註釋內容
]]--
內置數據類型
總共有6種內置數據類型, 其中包括nil, boolean, number, string, table, function
nil
通常是沒有賦值,直接使用纔會是這個值, 比如說下面的代碼直接打印變量name lua print(name), 在 ifelse 判斷語句中,nil 被當成false 分支,但 nil ~= false, 在 Lua 語言當中,不等於使用 ~= 來表示, 而不是我們常見的 != 。
boolean
有兩種取值:true, false
number
所有的數值類型都使用 number 來表示,不管是整數,還是浮點數,其實內部的存儲方式是雙精度類型。
string
字符串可以用雙引號,也可以用單引號包圍起來,特殊字符需要轉義
name = "dev4mobile"
name = 'dev4mobile'
nameWithAge = 'dev4mobile \n 25'
# 多行字符串
welcome = [[
hello world
]]
table
其實就是其它語言裏面的對象, 有兩種表現方式,一種是數組,一種是字典(Map),都是使用大括號括起來的。記住數組索引從1開始。
arr = { 1, "dev4mobile", '[email protected]', 12.3, function()endv}
person = { name = 'dev4mobile' }
function
定義如下,以 function關鍵字作爲開頭,add 是函數名字
-- 一般定義
function add(a, b)
return a + b
end
-- 傳遞多個參數
function dd(...)
local args = {...}
for i, v in ipairs(args) do
print("參數", i, ":", v)
end
end
-- 返回多個參數
function res()
return "abc", 12, function() end
end
local value1, value2, value3 = res()
控制流語句
循環
循環有3種寫法,for, while,repeat .. until
說明: #變量名 表示讀取變量的長度,可以是字符串和數組
-- for 循環
arr = { 1, 2, 3, 4, 5 }
for i=1, #arr do -- 索引從1開始
print(arr[i])
end
-- while 循環
arr = { 1, 2, 3, 4, 5 }
i = 1
while i <= #arr do
print(arr[i])
i = i + 1
end
-- repeate until 循環
arr = { 1, 2, 3, 4, 5 }
i = 1
repeat
print(arr[i])
i = i + 1
until i >= #arr
分支 ( ifelse )
name = "dev4mobile"
if #name > 10 then
print("name length = ".. #name)
elseif #name >5 then
print("name length > 5, real length = "..#name) -- 兩個點..代表字符串
else
print("name length < "..#name)
end
面向對象
實現原理:有點類似 JavaScript 的實現使用原型方式,使用函數 + table 實現。
模塊
在寫demo之前有必要先介紹下模塊的概念,一般來說一個文件就是一個模塊,跟 JavaScript 一樣, 導入模塊關鍵字 require, 導出模塊關鍵字return
下面我們來新建一個模塊名,首先新建一個文件名: perosn.lua,輸入下面代碼
-- 定義模塊
-- 解釋器
#!/usr/local/bin/lua
local Person = {}
-- 導出模塊名,類似JavaScript中的export
return Person
-- 導入模塊
-- 解釋器
#!/usr/local/bin/lua
local perosn = require('person')
構造對象
首先新建一個文件名: perosn.lua,輸入下面代碼
-- 定義模塊
-- 解釋器
#!/usr/local/bin/lua
local Person = {}
-- 定義構造函數
function Person:new(name, age)
-- __index 指向 父類 table
-- setmetatable 關聯了 新創建的對象 { name = name, age = age } 與 Person 對象
return setmetatable({ name = name, age = age }, { __index = Person })
end
function Person:toString()
print('name='..self.name..', age='..self.age)
end
-- 導出模塊名,類似JavaScript中的export
return Person
-- 導入模塊
-- 解釋器
#!/usr/local/bin/lua
local Perosn = require('person')
-- 調用構造函數
local person = Person:new("dev4mobile", 21)
-- 調用對象的toString方法, 這個方法是父類方法,需要我們setmetatable來綁定,也就是我們定義對象時 setmetatable({ name = name, age = age }, { __index = Person }) 來綁定的
person.toString()
異常處理
在Lua中是支持異常處理的。Lua提供了pcall
函數來捕獲函數執行過程中可能拋出的錯誤。下面是一個簡單的示例:
function divide(a, b)
if b == 0 then
error("除數不能爲0")
end
return a / b
end
local status, result = pcall(divide, 10, 0)
if status then
print("結果:", result)
else
print("發生錯誤:", result)
end
在上面的例子中,我們定義了一個divide
函數用於進行除法運算,如果除數爲0,則會通過error
函數拋出一個錯誤。然後我們使用pcall
來調用divide
函數,如果函數執行成功,pcall
返回true和函數的返回值;如果函數執行過程中有錯誤,pcall
返回false和錯誤信息。通過判斷pcall
的返回值,我們可以進行相應的異常處理。
冒號(:)和點號(.)的區別
在Lua中,使用冒號(:)和點號(.)的區別在於函數定義時是否將self作爲第一個參數傳入。
- 使用冒號(:)定義的方法會自動將調用該方法的對象作爲第一個參數傳入,通常約定將這個參數命名爲
self
。這樣,在方法內部就可以通過self
來訪問對象的成員變量和其他方法。 - 使用點號(.)定義的方法則不會自動傳入對象本身作爲第一個參數,需要手動傳入或者直接訪問全局變量。
下面是代碼示例:
local Person = {}
function Person:new(name, age)
local obj = {}
obj.name = name
obj.age = age
function obj:sayName()
print("My name is " .. self.name)
end
return obj
end
function Person.old(self, name, age)
self.name = name
self.age = age
function self.sayName()
print("My name is " .. self.name)
end
end
-- 使用冒號調用new方法
local person1 = Person:new("Alice", 25)
person1:sayName()
-- 使用點號調用old方法
local person2 = {}
Person.old(person2, "Bob", 30)
person2.sayName(person2)
在上面的例子中,Person:new
方法使用冒號定義,自動傳入了self
參數;而Person.old
方法使用點號定義,需要手動傳入self
參數。