免费赠送一个让Lua Table变成只读的代码,如果使用Lua作为配置表,有必要让table变成只读的,防止运行时被误改。此题也是我对有Lua使用经验者的应试者常用的面试题:)

local M = {}

local function readOnlyTableIter_pairs(t, k)
    local v
    k, v = next(t.__readonly, k)
    if v ~= nil then return k, v end
end

local function readOnlyTableIter_ipairs(t, i)
    i = i + 1
    local v = t.__readonly[i]
    if v ~= nil then return i, v end
end

function M.MakeReadOnly(t)
    assert(type(t) == "table", "except table at parameter 1")
    assert(getmetatable(t) == nil, "table already has metatable")

    for k, v in pairs(t) do
        if type(v) == "table" then
            t[k] = M.MakeReadOnly(v, includeChildren)
        end
    end

    return setmetatable({__readonly=t}, {
        __index = t,
        __newindex = function() error("Can't modify read-only table") end,
        __pairs = function(_t)
            return readOnlyTableIter_pairs, _t, nil
        end,
        __ipairs = function(_t)
            return readOnlyTableIter_ipairs, _t, 0
        end,
        __len = function(_t)
            return #_t.__readonly
        end,
        __metatable = false,
    })
end

return M