學習 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", 'cn.dev4mobile@gamil.com', 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
引數。