Lua语法入门-变量和循环

一、前言:为什么先学变量和循环?

在 Redis 中编写 Lua 脚本时,你最常写的代码就是:

  • 定义变量存储 key 或参数
  • 用循环遍历多个 key 执行操作

变量和循环是 Lua 脚本的"地基"。掌握它们,你就能写出安全、高效的原子操作!

本文将带你彻底搞懂 Lua 的变量作用域、数据类型、三大循环结构,并结合 Redis 场景实战演示。


二、Lua 变量:简单但有"坑"

2.1 变量无需声明,直接赋值

Lua 复制代码
name = "Alice"    -- 字符串
count = 100       -- 数字(整数/浮点统一)
isOk = true       -- 布尔值
empty = nil       -- 空值

动态类型:变量类型由值决定,运行时可变。

2.2 全局变量 vs 局部变量(重点!)

全局变量(不推荐)
Lua 复制代码
x = 10  -- 默认是全局变量,所有脚本共享
局部变量(强烈推荐!)
Lua 复制代码
local y = 20  -- 仅在当前作用域有效

⚠️ Redis 脚本最佳实践始终用 local 声明变量

原因:

  • 避免污染全局环境
  • 提升性能(局部变量访问更快)
  • 防止多脚本间意外干扰

2.3 特殊值:nil 和 false

Lua 中只有两个"假"值:

  • nil(未定义)
  • false

💡 注意:0、空字符串 ""、空表 {} 都是"真"

Lua 复制代码
if 0 then print("0 是真") end        --> 输出
if "" then print('"" 是真') end      --> 输出

三、Lua 循环:三种方式全解析

Lua 提供三种循环结构:whilerepeat-untilfor。其中 for 最常用


3.1 while 循环:条件为真时重复

Lua 复制代码
local i = 1
while i <= 3 do
    print(i)
    i = i + 1
end
-- 输出:1 2 3

🔧 适用场景:不确定循环次数,依赖动态条件。


3.2 repeat-until 循环:至少执行一次

Lua 复制代码
local j = 5
repeat
    print(j)
    j = j - 1
until j < 3
-- 输出:5 4 3

🔁 特点:先执行,再判断(类似 C/Java 的 do-while)。


3.3 for 循环:最常用!分两种

(1) 数值 for(推荐用于计数)
Lua 复制代码
-- 语法:for 变量 = 起始, 结束 [, 步长] do ... end
for i = 1, 5 do
    print(i)
end
-- 输出:1 2 3 4 5

-- 带步长(递减)
for k = 10, 1, -2 do
    print(k)
end
-- 输出:10 8 6 4 2

优点:简洁、高效、自动管理变量生命周期。

(2) 泛型 for(用于遍历 table)
Lua 复制代码
-- 遍历数组(注意:Lua 数组索引从 1 开始!)
local fruits = {"apple", "banana", "orange"}
for index, value in ipairs(fruits) do
    print(index, value)
end
-- 输出:
-- 1	apple
-- 2	banana
-- 3	orange

-- 遍历字典(无序)
local user = {name = "Bob", age = 30}
for key, value in pairs(user) do
    print(key, value)
end

🔑 关键区别

  • ipairs():只遍历连续数字索引(1,2,3...)
  • pairs():遍历所有键值对(包括字符串 key)

四、Redis 脚本实战:变量 + 循环的典型用法

场景:批量删除以 "temp:" 开头的 key

错误写法(在 Lua 中不能用 KEYS 模糊匹配!)
Lua 复制代码
-- ❌ Redis 不支持在 Lua 中执行 KEYS * 命令!
正确做法:客户端传入 key 列表
Lua 复制代码
-- 脚本:delete_keys.lua
for i = 1, #KEYS do
    redis.call('DEL', KEYS[i])
end
return #KEYS
在 Java 中调用(Spring Boot)
java 复制代码
List<String> keysToDelete = Arrays.asList("temp:1", "temp:2", "temp:3");

Long deleted = redisTemplate.execute(
    new DefaultRedisScript<>("for i=1,#KEYS do redis.call('DEL',KEYS[i]) end return #KEYS", Long.class),
    keysToDelete
);
System.out.println("删除了 " + deleted + " 个 key");

关键点

  • #KEYS 表示 KEYS 表的长度(Lua 中 # 用于获取数组长度)
  • 循环从 1#KEYS(因为 Lua 数组索引从 1 开始!)

五、常见误区与避坑指南

❌ 误区 1:数组索引从 0 开始

  • 错误for i = 0, #KEYS-1 do ... KEYS[i] ...
  • 正确for i = 1, #KEYS do ... KEYS[i] ...

❌ 误区 2:忘记用 local

  • 危险i = 1 → 全局变量,可能被其他脚本修改
  • 安全local i = 1

❌ 误区 3:在循环中修改 table 长度

  • 问题:边遍历边删除元素,可能导致跳过或崩溃
  • 建议:先收集要删除的 key,再统一处理

六、小结:核心要点速记

主题 关键规则
变量 local 声明;只有 nilfalse 为假
数组索引 从 1 开始!不是 0
数值 for for i = 1, 10 do ... end
遍历数组 ipairs()
遍历字典 pairs()
Redis 脚本 KEYSARGV 是 table,索引从 1 开始

七、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
csbysj20202 小时前
CSS 颜色
开发语言
2401_833197732 小时前
C++代码切片分析
开发语言·c++·算法
是翔仔呐2 小时前
第13章 超声波测距传感器驱动:HC-SR04底层原理与C语言实现
c语言·开发语言·单片机·嵌入式硬件·gitee
m0_621438522 小时前
实时音频处理C++实现
开发语言·c++·算法
weixin_421922692 小时前
模板代码性能测试
开发语言·c++·算法
Red丶哞2 小时前
内网自建Postfix使用Python发送邮件
开发语言·python
静心观复2 小时前
使用 new 关键字和 Java 反射创建对象的区别
java·开发语言
Liu628882 小时前
C++中的模板方法模式
开发语言·c++·算法
qq_334903152 小时前
高性能网络协议栈
开发语言·c++·算法