最近在项目中遇到框架上设计的lua只读表,在使用next对表判空时出现一直为nil的情况,后来研究了下只读表的生成,特此记录。
-- lua只读表的生成代码 XReadOnlyTable.Create = function(t) for x, y in pairs(t) do if type(x) == "table" then if type(y) == "table" then t[XReadOnlyTable.Create(x)] = XReadOnlyTable.Create(y) else t[XReadOnlyTable.Create(x)] = y end elseif type(y) == "table" then t[x] = XReadOnlyTable.Create(y) end end local mt = { __metatable = "readonly table", __index = t, __newindex = function() XLog.Error("attempt to update a readonly table") end, __len = function() return #t end, __pairs = function() local function stateless_iter(tbl, k) local nk, nv = next(tbl, k) if nk then return nk, nv end end return stateless_iter, t, nil end } return setmetatable({}, mt) -- 返回一个空表 end -- 测试代码 function Test() local tableA = {1,2,3,4,5,6,7,8,9} local tableB = XReadOnlyTable.Create(tableA) XLog.Debug(next(tableB)) XLog.Debug(tableA[1]) end -- 打印 nil 1代码中可以看出,生成只读表的时候返回了一个空表,也就是说tableB是个带有自己设定好特殊原表的空表,在使用next调用tableB的时候,也是调用的这个空表,所以返回的是nil。 而按照索引对表进行访问的时候,由于访问空表找不到元素值,就去访问原表,找到了带有数据的tableA,返回指定索引数据。 在日后对表判空还是建议使用next,对于项目内自定义的只读表还要多加注意。