Lua语法入门-条件控制、函数

一、前言:为什么条件和函数是 Lua 脚本的核心?

在 Redis 中,你经常需要实现这样的逻辑:

  • "如果库存足够,就扣减;否则返回失败"
  • "对多个 key 执行相同操作,避免重复代码"

条件控制(if)决定逻辑分支,函数(function)实现代码复用 ------它们是构建健壮、可维护 Lua 脚本的两大支柱!

本文将带你深入掌握 Lua 的 if 语句、布尔逻辑、函数定义与调用,并结合 Redis 实战演示。


二、条件控制:if 语句全解析

Lua 的条件判断非常简洁,但有两个关键细节必须注意!

2.1 基本语法

Lua 复制代码
if condition1 then
    -- 执行块1
elseif condition2 then
    -- 执行块2
else
    -- 执行块3
end

2.2 关键规则 1:只有 nil 和 false 是"假"

Lua 复制代码
-- 以下值在 if 中都为"真"!
if 0 then print("0 是真") end          --> 输出
if "" then print('空字符串是真') end   --> 输出
if {} then print("空表是真") end       --> 输出

-- 只有这两个是"假"
if nil then else print("nil 是假") end
if false then else print("false 是假") end

⚠️ 常见坑 :不要写 if count == nil or count == 0,直接 if not count 即可(但注意 0 是真!)

2.3 关键规则 2:关系运算符

运算符 含义
== 相等
~= 不等(不是 !=)
<, >, <=, >= 比较大小
Lua 复制代码
local a = 10
local b = "10"

print(a == b)  --> false(类型不同)
print(a == tonumber(b)) --> true

建议 :比较前统一类型(如用 tonumber() 转数字)


三、实战:Redis 脚本中的条件判断

场景:安全扣减库存(防止超卖)

Lua 复制代码
-- safe_decr_stock.lua
local stock_key = KEYS[1]
local decr_amount = tonumber(ARGV[1])

-- 获取当前库存(字符串转数字)
local current = redis.call('GET', stock_key)
if not current then
    -- 库存未初始化
    return 0
end

local stock = tonumber(current)
if stock >= decr_amount then
    redis.call('DECRBY', stock_key, decr_amount)
    return 1  -- 成功
else
    return 0  -- 库存不足
end

优势 :整个判断+修改过程原子执行,无并发问题!


四、函数(Function):代码复用的关键

4.1 定义函数

Lua 复制代码
-- 方式1:标准定义
function add(a, b)
    return a + b
end

-- 方式2:变量赋值(等价)
add = function(a, b)
    return a + b
end

4.2 调用函数

Lua 复制代码
local result = add(3, 5)
print(result)  --> 8

4.3 函数特性

  • 多返回值

    Lua 复制代码
    function get_name_age()
        return "Alice", 25
    end
    local name, age = get_name_age()
  • 可变参数

    Lua 复制代码
    function sum(...)
        local args = {...}
        local total = 0
        for i = 1, #args do
            total = total + args[i]
        end
        return total
    end
    print(sum(1, 2, 3))  --> 6

💡 提示 :Redis 脚本中不推荐使用可变参数,因 ARGV 已是 table。


五、Redis 脚本中的函数实践

场景:封装"获取并转数字"逻辑

Lua 复制代码
-- utils.lua (嵌入到主脚本中)
local function get_number(key)
    local val = redis.call('GET', key)
    if not val then return 0 end
    return tonumber(val)
end

-- 主逻辑
local stock = get_number(KEYS[1])
local quota = get_number(KEYS[2])

if stock > 0 and quota > 0 then
    redis.call('DECR', KEYS[1])
    redis.call('DECR', KEYS[2])
    return "OK"
else
    return "INSUFFICIENT"
end

好处

  • 避免重复代码
  • 逻辑更清晰
  • 易于测试和维护

六、高级技巧:函数作为参数(高阶函数)

Lua 支持函数式编程风格:

Lua 复制代码
-- 定义一个通用遍历处理器
local function process_keys(key_list, handler)
    for i = 1, #key_list do
        handler(key_list[i])
    end
end

-- 使用
process_keys(KEYS, function(key)
    redis.call('EXPIRE', key, 3600)
end)

🔧 适用场景:批量设置过期时间、统一格式化等。


七、避坑指南:Redis 脚本中的函数限制

❌ 不能定义全局函数(除非必要)

Lua 复制代码
-- 危险!污染全局环境
function my_func() ... end

-- 安全:用 local
local function my_func() ... end

❌ 不能递归过深(Redis 有栈深度限制)

  • 避免深度递归,改用循环

❌ 函数内不能有随机行为

Lua 复制代码
-- 错误:math.random() 在 Redis 中禁止(除非固定种子)
local function random_val()
    return math.random(1, 10)  -- 可能导致主从不一致!
end

替代方案:随机数由客户端生成,通过 ARGV 传入。


八、小结:核心要点速记

主题 关键规则
if 判断 只有 nilfalse 为假;0、""、{} 都是真
不等于 ~=,不是 !=
函数定义 local function name(...) ... end
Redis 安全 函数必须是纯函数(无副作用、无随机)
代码复用 将通用逻辑(如类型转换)封装成 local 函数

九、结语

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

相关推荐
桌面运维家2 小时前
Win10打印机共享故障排查:权限与网络配置详解
开发语言·网络·php
Sunshine for you2 小时前
实时操作系统中的C++
开发语言·c++·算法
史蒂芬_丁2 小时前
C++深度拷贝例子
java·开发语言·c++
Knight_AL3 小时前
Nacos 启动问题 Failed to create database ’D:\nacos\nacos\data\derby-data’
开发语言·数据库·python
leiming63 小时前
CAN 通信协议学习讲义(带图文 + C 语言代码)
c语言·开发语言·学习
xht08324 小时前
PHP vs C语言:核心差异全解析
c语言·开发语言·php
yoothey4 小时前
Java字节流与字符流核心笔记(问答+考点复盘)
java·开发语言·笔记
查古穆4 小时前
python进阶-Pydantic模型
开发语言·python
沐知全栈开发4 小时前
Bootstrap4 导航栏
开发语言