lua~基本語法

张占岭發表於2024-05-11

學習 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引數。