Lua基本语法

Lua 基本语法详解

1. 注释

-- 单行注释

--[[
    多行注释
    可以写很多行
--]]

---@class MyClass  -- 注解注释(用于 IDE 类型提示)

2. 变量和数据类型

变量声明

local x = 10        -- 局部变量(推荐)
y = 20              -- 全局变量(不推荐)
local a, b, c = 1, 2, 3  -- 多重赋值

8种数据类型

local n = nil               -- 空值
local b = true              -- 布尔值:true/false
local num = 3.14            -- 数字(整数和浮点数)
local str = "hello"         -- 字符串
local func = function() end -- 函数
local tbl = {}              -- 表(table)
local thread = coroutine.create(function() end)  -- 协程
local ud = nil              -- userdata(C数据)

-- 检查类型
print(type(n))      -- nil
print(type(b))      -- boolean
print(type(num))    -- number

3. 字符串

local s1 = "单引号"
local s2 = '双引号'
local s3 = [[
    多行字符串
    保留换行和空格
]]

-- 字符串连接
local result = "Hello" .. " " .. "World"

-- 字符串长度
print(#"Hello")  -- 5

-- 常用字符串函数
string.upper("hello")       -- "HELLO"
string.lower("HELLO")       -- "hello"
string.sub("hello", 1, 2)   -- "he"
string.format("%d + %d = %d", 1, 2, 3)  -- "1 + 2 = 3"
string.find("hello", "ll")  -- 3, 4
string.gsub("hello", "l", "L")  -- "heLLo"

4. 运算符

算术运算符

local a = 10 + 5   -- 加法:15
local b = 10 - 5   -- 减法:5
local c = 10 * 5   -- 乘法:50
local d = 10 / 5   -- 除法:2.0
local e = 10 % 3   -- 取模:1
local f = 10 ^ 2   -- 幂运算:100
local g = -10      -- 负号

关系运算符

10 == 10   -- 等于:true
10 ~= 5    -- 不等于:true
10 > 5     -- 大于:true
10 < 5     -- 小于:false
10 >= 10   -- 大于等于:true
10 <= 5    -- 小于等于:false

逻辑运算符

true and false  -- 与:false
true or false   -- 或:true
not true        -- 非:false

-- 短路求值
local x = nil
local y = x or 10  -- y = 10(x为nil时使用默认值)
local z = x and x.value  -- z = nil(避免访问nil)

其他运算符

#"hello"     -- 长度运算符:5
#tbl         -- 表的长度
"ab".."cd"   -- 字符串连接:abcd

5. 控制结构

if 语句

local score = 85

if score >= 90 then
    print("优秀")
elseif score >= 60 then
    print("及格")
else
    print("不及格")
end

-- 三元运算符的替代
local result = (score >= 60) and "及格" or "不及格"

while 循环

local i = 1
while i <= 5 do
    print(i)
    i = i + 1
end

repeat-until 循环

local i = 1
repeat
    print(i)
    i = i + 1
until i > 5  -- 注意:条件为真时退出

for 循环

-- 数值for循环
for i = 1, 10 do
    print(i)  -- 1到10
end

for i = 1, 10, 2 do
    print(i)  -- 1, 3, 5, 7, 9(步长为2)
end

for i = 10, 1, -1 do
    print(i)  -- 10到1(倒序)
end

-- 泛型for循环(遍历表)
local tbl = {10, 20, 30}
for index, value in ipairs(tbl) do
    print(index, value)
end

local dict = {name="张三", age=20}
for key, value in pairs(dict) do
    print(key, value)
end

break 和 goto

for i = 1, 10 do
    if i == 5 then
        break  -- 跳出循环
    end
    print(i)
end

-- goto(Lua 5.2+)
::retry::
print("尝试连接...")
if not connected then
    goto retry
end

6. 函数

函数定义

-- 基本定义
function add(a, b)
    return a + b
end

-- 匿名函数
local multiply = function(a, b)
    return a * b
end

-- 多返回值
function getMinMax(a, b)
    if a < b then
        return a, b
    else
        return b, a
    end
end

local min, max = getMinMax(10, 5)  -- min=5, max=10

可变参数

function sum(...)
    local args = {...}  -- 打包成表
    local total = 0
    for _, v in ipairs(args) do
        total = total + v
    end
    return total
end

print(sum(1, 2, 3, 4, 5))  -- 15

闭包

function makeCounter()
    local count = 0
    return function()
        count = count + 1
        return count
    end
end

local counter = makeCounter()
print(counter())  -- 1
print(counter())  -- 2

7. 表(Table)

创建表

local arr = {10, 20, 30}  -- 数组(索引从1开始)
local dict = {name="张三", age=20}  -- 字典
local mixed = {10, 20, name="张三"}  -- 混合

访问表

-- 数组访问
print(arr[1])  -- 10

-- 字典访问
print(dict["name"])  -- 张三
print(dict.name)     -- 张三(语法糖)

-- 添加元素
arr[4] = 40
dict.gender = "男"

表操作

-- 插入
table.insert(arr, 40)      -- 末尾插入
table.insert(arr, 1, 5)    -- 指定位置插入

-- 删除
table.remove(arr)          -- 删除最后一个
table.remove(arr, 1)       -- 删除指定位置

-- 连接
local str = table.concat(arr, ", ")  -- "10, 20, 30"

-- 排序
table.sort(arr)            -- 升序
table.sort(arr, function(a, b) return a > b end)  -- 降序

-- 长度
print(#arr)  -- 数组部分的长度

遍历表

local tbl = {10, 20, 30, name="张三"}

-- ipairs:只遍历数组部分(连续整数索引)
for i, v in ipairs(tbl) do
    print(i, v)  -- 1,10  2,20  3,30
end

-- pairs:遍历所有键值对
for k, v in pairs(tbl) do
    print(k, v)  -- 1,10  2,20  3,30  name,张三
end

8. 面向对象(基于表和元表)

简单类

-- 定义类
local Person = {}
Person.__index = Person

-- 构造函数
function Person.new(name, age)
    local self = setmetatable({}, Person)
    self.name = name
    self.age = age
    return self
end

-- 方法
function Person:sayHi()
    print("Hi, I'm " .. self.name)
end

-- 使用
local p = Person.new("张三", 20)
p:sayHi()  -- Hi, I'm 张三

继承

local Student = {}
Student.__index = Student
setmetatable(Student, {__index = Person})

function Student.new(name, age, school)
    local self = Person.new(name, age)
    setmetatable(self, Student)
    self.school = school
    return self
end

function Student:study()
    print(self.name .. " is studying at " .. self.school)
end

9. 元表(Metatable)

local tbl = {value = 10}

local mt = {
    -- 算术运算
    __add = function(t1, t2) return t1.value + t2.value end,
    __sub = function(t1, t2) return t1.value - t2.value end,
    
    -- 访问不存在的键
    __index = function(t, key)
        return "Key not found: " .. key
    end,
    
    -- 设置键值
    __newindex = function(t, key, value)
        rawset(t, key, value * 2)
    end,
    
    -- 转字符串
    __tostring = function(t)
        return "Value: " .. t.value
    end,
    
    -- 调用表
    __call = function(t, x)
        return t.value + x
    end
}

setmetatable(tbl, mt)
print(tbl.abc)       -- Key not found: abc
tbl.new = 5          -- 实际存储 10
print(tbl(5))        -- 15

10. 模块

创建模块

-- mymodule.lua
local M = {}

function M.add(a, b)
    return a + b
end

function M.sub(a, b)
    return a - b
end

return M

使用模块

local mymodule = require("mymodule")
print(mymodule.add(10, 5))  -- 15

11. 错误处理

-- pcall(保护调用)
local success, result = pcall(function()
    return 10 / 0
end)

if success then
    print("结果:", result)
else
    print("错误:", result)
end

-- xpcall(带错误处理函数)
local function errorHandler(err)
    return "错误: " .. tostring(err)
end

xpcall(function()
    error("出错了")
end, errorHandler)

-- assert(断言)
local x = nil
assert(x, "x 不能为 nil")  -- 如果x为nil则抛出错误

12. 协程(Coroutine)

local co = coroutine.create(function()
    for i = 1, 3 do
        print("协程:", i)
        coroutine.yield()  -- 暂停
    end
end)

coroutine.resume(co)  -- 协程: 1
coroutine.resume(co)  -- 协程: 2
coroutine.resume(co)  -- 协程: 3

print(coroutine.status(co))  -- dead

13. 常用全局函数

-- 类型相关
type(x)           -- 返回类型
tonumber("123")   -- 转数字:123
tostring(123)     -- 转字符串:"123"

-- 输出
print("Hello")    -- 打印

-- 数学
math.abs(-10)     -- 绝对值:10
math.ceil(3.2)    -- 向上取整:4
math.floor(3.8)   -- 向下取整:3
math.max(1,2,3)   -- 最大值:3
math.min(1,2,3)   -- 最小值:1
math.random()     -- 随机数 [0,1)
math.random(10)   -- 随机整数 [1,10]
math.pi           -- π

-- 操作系统
os.time()         -- 当前时间戳
os.date()         -- 格式化时间
os.clock()        -- CPU时间

14. 重要注意事项

索引从1开始

local arr = {10, 20, 30}
print(arr[1])  -- 10(不是arr[0])

nil 和 false 的区别

local x = nil
local y = false

if not x then print("x is falsy") end  -- 输出
if not y then print("y is falsy") end  -- 输出

-- 但在表中:
local tbl = {a = nil, b = false}
print(tbl.a)  -- nil(键不存在)
print(tbl.b)  -- false(键存在,值为false)

局部变量优先

local x = 10

function test()
    local x = 20  -- 局部变量,不影响外部
    print(x)      -- 20
end

test()
print(x)          -- 10

冒号和点号

-- 冒号会自动传递self
obj:method(arg)   -- 等价于 obj.method(obj, arg)

-- 点号需要手动传递
obj.method(obj, arg)

posted on 2025-10-20 15:42  阿华小青蛙  阅读(91)  评论(0)    收藏  举报