为什么空值检查会失败

我正在使用 Lua 查询 redis 并想要检查一个键是否不存在,但是我很困惑为什么我的代码不起作用:

local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
    if (i == 1) then
        if (v == nil) then
            return nil  -- 这里永远不会执行
        end
    end
end

但是以下代码可以正常工作:

local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
    if (i == 1) then
        v = v or 0
        if (v == 0) then
            return nil  -- 这里可以执行
        end
    end
end

到底是怎么回事?

点赞
用户2858170
用户2858170

你正在使用ipairs来迭代你的表格。迭代将在第一个nil元素处结束。因此,在循环中,v永远不会等于nil。因此,你永远不会进入if(v==nil)语句。

来自Lua参考手册6.1基本函数:

ipairs(t)返回三个值(迭代器函数、表格t和0),以便构造

for i,v in ipairs(t) do body end

将迭代键值对(1,t [1]),(2,t [2]),…,直到第一个nil值。

实际上,你不能使用任何标准迭代器来查找nil值。

如果你只想检查bulk [1]是否为nil

local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
    if (i == 1) then
        if (v == nil) then
            return nil  -- This is never entered
        end
    end
end

替换为

local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
if not bulk[1] then return end

returnreturn nil是相同的。

如果bulk [1]可能有效地为false,则明确检查nil

if bulk[1] == nil then return end

这段代码:

local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
    if (i == 1) then
        v = v or 0
        if (v == 0) then
            return nil  -- This does work
        end
    end
end

可以工作,因为bulk [1]要么是0,要么是false,在这种情况下,你将其替换为0

快速研究确认,Redis Lua绑定返回false值而不是nil。因此,使用ipairs应该没问题。你应该只检查该值是否等于false,而不是nil

2019-04-09 11:16:17