Lua语法详解:从变量声明到循环遍历的避坑指南

在上一篇文章中,我们认识了 Lua 这种轻量级脚本语言,并成功运行了 Hello World。但在实际的多级缓存开发(如 Nginx + OpenResty)中,仅仅会打印字符串是远远不够的。

Lua 的语法设计非常独特,它既像 Python 一样简洁,又像 Java 一样严谨,但又有许多"反直觉"的特性(比如数组下标从 1 开始)。今天,我们就来深入 Lua 的核心------变量与循环,帮你避开那些新手最容易踩的坑。

一、Lua 的数据类型:少即是多

与 Java 复杂的类型系统不同,Lua 只有寥寥几种基本类型,但却极其灵活。

  • nil(空值)
    • 表示无效值。在条件判断中,nil 和 false 都会被当作"假",而其他任何值(包括 0 和空字符串 "")都被当作"真"。
    • 注意:这与 Java 的 null 不同,Java 的 null 不能直接参与逻辑运算。
  • boolean(布尔)
    • 只有 true 和 false。
  • number(数字)
    • Lua 不区分 int、float 或 double,所有数字默认都是双精度浮点数。
    • 示例:10.4 * 3 的结果依然是 number 类型。
  • string(字符串)
    • 支持单引号 ' 和双引号 ",两者等价。
    • 拼接:使用两个点 .. 操作符,例如 "Hello" .. "World"。
  • function(函数)
    • 函数在 Lua 中是"一等公民",可以像变量一样被赋值和传递。
  • table(表)
    • 这是 Lua 最强大的数据结构!它既是数组,也是 Map(哈希表)。
    • 创建:使用 {} 即可,例如 local arr = {}。

小技巧:如何判断类型?

使用 type() 函数,它会返回一个字符串表示类型:

复制代码
print(type("Hello")) -- 输出 "string"
print(type(10.4*3))  -- 输出 "number"
print(type(print))   -- 输出 "function"
二、变量声明:local 是必须的

在 Java 中,我们习惯写 int a = 10;。而在 Lua 中,声明变量非常简单,但有一个关键规则:一定要加 local

1. 声明语法

不需要指定类型,直接赋值即可:

复制代码
local str = 'hello'            -- 字符串
local num = 21                 -- 数字
local flag = true              -- 布尔
local arr = {'java', 'lua'}    -- 数组形式的 table
local map = {name='Jack', age=21} -- Map 形式的 table

2. 为什么要用 local?

  • 局部变量:使用 local 声明的变量,作用域仅限于当前代码块。
  • 全局变量:如果不加 local,变量默认是全局的。
  • 最佳实践 :在 Nginx 脚本中,为了避免污染全局环境并提升访问速度,请务必始终使用 local 声明变量

3. 访问 Table

Lua 的 table 非常灵活,访问方式也多种多样:

  • 数组访问
    • 注意!Lua 的数组下标从 1 开始,而不是 0!
    • 示例:print(arr1) 获取第一个元素。
  • Map 访问
    • 方式一(中括号):print(map'name'),类似 Java 的 map.get("name")。
    • 方式二(点号):print(map.name),类似 Java 的对象属性访问。
    • 两者完全等价,点号写法更简洁。
三、循环遍历:ipairs 与 pairs 的爱恨情仇

在 Java 中,我们遍历 List 用 for-each,遍历 Map 用 entrySet。在 Lua 中,我们需要根据 table 的形态选择不同的迭代器。

1. 遍历数组:使用 ipairs

当你把 table 当作数组(连续的数字索引)使用时,使用 ipairs。

复制代码
local arr = {'java', 'python', 'lua'}
for index, value in ipairs(arr) do
    print(index, value)
end
-- 输出: 1 java, 2 python, 3 lua

2. 遍历 Map:使用 pairs

当你把 table 当作字典(键值对)使用时,必须使用 pairs。

复制代码
local map = {name='Jack', age=21}
for key, value in pairs(map) do
    print(key, value)
end
-- 输出: name Jack, age 21 (顺序可能不固定)

避坑指南:

  • 遍历纯数组时,推荐用 ipairs,因为它效率更高且按顺序遍历。
  • 遍历包含非数字 Key 的 table 时,必须用 pairs。
总结与展望

Lua 的语法虽然简单,但 table 的灵活性和下标从 1 开始的设定往往是 Java 开发者最容易出错的地方。

掌握了变量和循环,我们就拥有了编写复杂逻辑的能力。接下来,我们就可以利用这些知识,去探索 Lua 的函数定义和模块管理,真正开始编写 Nginx 业务脚本了。


知识点核心总结
知识点 核心内容 考试重点/易混淆点 难度系数
Lua数据类型 nil(可表示false)、boolean、number(统一数值类型)、string(单/双引号)、function(可传递)、table(数组+map混合结构) nil与false的等价性、table的两种形态转换 ⭐⭐
变量声明 local声明局部变量(不加local为全局变量),无需指定类型 字符串拼接使用..运算符
table操作 数组角标从1开始、map支持table.key和table"key"两种访问方式 角标从1开始与多数语言差异 ⭐⭐
循环结构 for index,value in ipairs(arr)遍历数组 for key,value in pairs(map)遍历table ipairs/pairs函数选择 ⭐⭐
类型检测 type()函数返回类型字符串(nil/boolean/number/string/function/table) 检测函数类型返回"function"
语法特性 函数作为一等公民可赋值传递、table的灵活数据结构 设计与JAVA的类型系统差异对比 ⭐⭐⭐
相关推荐
小努蛋2 小时前
linux编译openresty异常问题,lua_cjson.c:706:5: 错误: ‘for‘ 循环初始化声明只在 C99 或 C++ 模式下允许
开发语言·lua·openresty
天疆说3 小时前
01 硬件选型与 llama.cpp 部署:4× RTX 5880 Ada 跑 DeepSeek-V4-Flash
java·redis·llama
嘟嘟07173 小时前
Next.js 博客左侧笔记列表是怎么从 Redis 渲染出来的?从组件、children 到动态路由一次讲清
redis·react.js·前端工程化
大飞记Python4 小时前
AI大模型Token计费全解析:输入/输出、缓存命中、阶梯计价一文看懂
人工智能·缓存
Rain的Java大神之路6 小时前
线上接口负载满了如何解决
java·数据库·redis·后端·缓存·面试·架构
Amir_zy8 小时前
Redis测试方法全攻略:冒烟、压测与稳定性验证
redis·压力测试
霸道流氓气质9 小时前
RedLock:Redis 分布式锁的高可用方案
数据库·redis·分布式
天疆说10 小时前
04 稳定性与性能调优实录:OOM 崩溃、并发槽位、前缀缓存与 DSpark 调参
linux·运维·缓存
csdn2015_10 小时前
springboot +mybatis 查询myql开启程序级别缓存
spring boot·缓存·mybatis
隔窗听雨眠10 小时前
缓存增强生成CAG:用预加载KV缓存突破RAG实时检索瓶颈
缓存