Lua 的基本内容

值和类型

8 中基本类型

类型说明
nilnil类型只有一个值,通常表示不存在有用的值
booleannil 和 false 为假,其余均为真值
number整数和浮点数
string不可变的字节序列
function
userdata用户数据值在 Lua 中无法创建或修改,只能通过 C API 进行创建或修改
thread线程类型
table关联数组

表、函数、线程和(完整的)用户数据值都是对象 :变量实际上并不包含这些值,而只是对它们的引用 。赋值、参数传递和函数返回始终操作的是对这些值的引用;这些操作不涉及任何形式的复制。

环境和全局变量

Lua 把你没定义过的变量,都当作是 _ENV 这个表里的成员。_ENV 就是一个普通的 Lua 表(table),它用来当“作用域环境”。默认这个 _ENV 就是 _G 也就是平时说的全局变量表。

-- _ENV 可以被改掉
local _ENV = {print = function() print("你被劫持了") end}


-- 如果要加载一个 lua 脚本,不想让它访问全局变量,可以使用 load / loadfile
local f = load("print(x)", nil, "t", { print = print, x = 123 })
f()  -- 输出 123

-- 这个 { print = print, x = 123 } 就是传给这个脚本的 _ENV,它用来隔离变量作用域

错误处理

功能用法说明
抛出错误error(“错误了”)
捕获错误pcall(function)
带堆栈处理器xpcall(func, handler)
错误值可以是字符串、table、数字……任意值
警告机制只提示不影响程序运行,从 Lua 5.4 开始支持
-- 抛出错误
--error("发生了致命错误")

-- pcall 捕获错误
local ok, result = pcall(function()
  error("boom")
end)

print(ok)
print(result)

-- 自定义处理错误 xpcall
local function my_func()
  error("出问题了")
end

local function my_handler(err)
  return "捕获错误: " .. err .. "\n" .. debug.traceback()
end

local ok, msg = xpcall(my_func, my_handler)
print(msg)
  • 自定义错误处理
local function log_error(msg)
  io.stderr:write("[ERROR] " .. os.date() .. "\n" .. msg .. "\n")
end

function safe_call(fn, ...)
  local args = { ... }

  local function error_handler(err)
    local msg = tostring(err)
    local trace = debug.traceback("", 2)
    local full_msg = "【Lua错误】" .. msg .. "\n" .. trace
    log_error(full_msg)
    return full_msg
  end

  local function wrapped()
    return fn(table.unpack(args))
  end

  local ok, result = xpcall(wrapped, error_handler)
  return ok, result
end


local function demo(a, b)
  return a / b
end

local ok, res = safe_call(demo, 10, 0)
if not ok then
  print("执行失败: ")
  print(res)
else
  print("执行成功,结果是: " .. res)
end

元表和元方法

Lua 的 metatables 和 metamethods 允许自定义 lua 对象的行为。

项目描述
元表是一个普通 Lua 表,附加在某个值上,用来定义额外行为
元方法是元表中特定名称的字段(比如 __add),用来触发特殊操作
作用对象表(table)最常用,也可以用于 full userdata、字符串等
常见用途模拟类和对象、运算符重载、自定义打印、自定义函数调用等
获取元表getmetatable(x)
设置元表setmetatable(t, mt)
  • 示例 让表像函数一样使用(__call)
local t = {}

setmetatable(t, {
	__call = function(self, name)
		print("你好," .. name)
	end
})

t("mako") --> 你好,mako

lua 内置的元方法都有固定的名称,默认以双下划线开头。

元表键说明
__add如果加法运算中的任何操作数不是数字,Lua 就会尝试调用元方法
__sub减法( - )运算。行为类似于加法运算
__mul乘法运算。行为类似于加法运算
__div除法运算。行为类似于加法运算
__mod取模运算
__pow幂运算
__unm否定运算
__idiv向下取整运算
__band按位与运算
__bor按位或运算
__bxor按位异或运算
__bnot按位非或运算
__shl按位左移运算
__shr按位右移运算
__concat连接(..)操作
__len长度 (#) 操作
__eq相等 == 操作
__lt小于运算
__le小于等于
__index索引访问 table[key]
__newindex索引赋值 table[key] = value
__call调用操作 func(args)
__gc
__mode
__close
__name

垃圾回收

  • Lua 垃圾回收的核心技巧
主题说明
自动 GC大多数情况下不用操心,Lua 会帮你清理
手动优化在高频率创建对象时可主动控制 GC 步进或清理时机
循环引用Lua 可以识别并正确回收
弱引用表非常适合做缓存系统,避免“持有太久”
自定义清理在 userdata + __gc 元方法中定义“析构器”逻辑

携程

协程是轻量级线程,但它不像系统线程那样自动调度,而是你手动控制何时执行、何时暂停。

协程的核心函数有:

  • coroutine.create(fn):创建协程
  • coroutine.resume(co, ...):启动或恢复协程执行
  • coroutine.yield(...):协程主动让出控制权
  • coroutine.status(co):获取协程状态
  • coroutine.wrap(fn):封装协程为函数调用
flowchart TD
    A[新建 coroutine.create] --> B[挂起状态 suspended]
    B -->|coroutine.resume| C[运行中 running]
    C -->|coroutine.yield| B
    C -->|return/结束| D[已结束 dead]

语言

  • 变量命名规则可以包含数字,字母和下划线且不能以数字开头;不能为系统保留关键字
    • 区分大小写
  • 按照惯例,程序应避免创建以下划线开头,后跟一个或多个大写字母的名称;如 _VERSION
  • 系统保留关键字
and       break     do        else      elseif    end
false     for       function  goto      if        in
local     nil       not       or        repeat    return
then      true      until     while

- 注释

```lua
-- 这是单行注释

--[[
  多行注释
]]
  • 字符串字面量
-- 1. 使用匹配的单引号或双引号
-- 2. 长字符串字面量 以特殊格式 [[ ... ]] 或 [=[ ... ]=] 等形式包围,可以跨行,不解释任何转义序列
a = [[
hello
World"]]

语句

  • 支持多值赋值。多值超出或不足时,自动填 nil 或忽略多余。
x, y, z = 1, 2          -- z 为 nil
a, b = 3, 4, 5          -- 第三个值 5 被忽略
  • 局部变量声明使用 local
  • 控制语句
-- if

-- while

while condition do
	-- body
end

-- repeat ... until 循环 先执行一次再判断
repeat
	-- body
until condition


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

-- for 循环迭代器
for k, v in pairs(tabl) do
  print(k, v)
end