时间:2021-05-22
项目中部分只读表易被人误改写,故决定在非线上环境里对这些表附加只读属性,方便在出现误改写的时候抛出lua错误,最终版代码如下:
--[[-------------------------------------------------------------------------------** 设置table只读 出现改写会抛出lua error-- 用法 local cfg_proxy = read_only(cfg) retur cfg_proxy-- 增加了防重置设置read_only的机制-- lua5.3支持 1)table库支持调用元方法,所以table.remove table.insert 也会抛出错误,-- 2)不用定义__ipairs 5.3 ipairs迭代器支持访问元方法__index,pairs迭代器next不支持故需要元方法__pairs-- 低版本lua此函数不能完全按照预期工作*]]function read_only(inputTable) local travelled_tables = {} local function __read_only(tbl) if not travelled_tables[tbl] then local tbl_mt = getmetatable(tbl) if not tbl_mt then tbl_mt = {} setmetatable(tbl, tbl_mt) end local proxy = tbl_mt.__read_only_proxy if not proxy then proxy = {} tbl_mt.__read_only_proxy = proxy local proxy_mt = { __index = tbl, __newindex = function (t, k, v) error("error write to a read-only table with key = " .. tostring(k)) end, __pairs = function (t) return pairs(tbl) end, -- __ipairs = function (t) return ipairs(tbl) end, 5.3版本不需要此方法 __len = function (t) return #tbl end, __read_only_proxy = proxy } setmetatable(proxy, proxy_mt) end travelled_tables[tbl] = proxy for k, v in pairs(tbl) do if type(v) == "table" then tbl[k] = __read_only(v) end end end return travelled_tables[tbl] end return __read_only(inputTable)end测试代码如下:
local t0 = {k = 1}local t2 = { fdsf = {456}}local t1 = { a = {456, 89}, b = {456,ddss = 9, t2 = t2}, d = 45, e = "string",}t1.c=t1local t3 = read_only(t1)print(t3.d, t3.c.e, t3.c.c.b.t2.fdsf)function q1() t3.d = 4555 endfunction q2() t3.c.d = 90 endfunction q3() t3.c.c.b.t2.fdsf =90 endfunction q4() table.remove(t3.a) endfunction q5() t3.b[ddss] = nil endfunction q6() t3[f] = 89 endfunction q7() table.insert(t3.a, 999) endprint(pcall(q1))print(pcall(q2))print(pcall(q3))print(pcall(q4))print(pcall(q5))print(pcall(q6))print(pcall(q7))print(t3.a[1])for k,v in pairs(t3) do print("===pairs t3:",k,v)endfor k,v in pairs(t3.a) do print("===pairs t3.a:",k,v)endfor k,v in ipairs(t3) do print("===ipairs t3:",k,v)endfor k,v in ipairs(t3.a) do print("===ipair t3.a",k,v)endprint("len t3:",#t3)print("len t3.a:", #t3.a)local t4 = read_only(t2)local t5 = read_only(t0)local t6 = read_only(t0)print(t3.b.t2, read_only(t2))print(t5, t6, t0)测试环境https://www.lua.org/cgi-bin/demo lua5.3.4:
string table: 0x20d4ba0false input:17: error write to a read-only table with key = dfalse input:17: error write to a read-only table with key = dfalse input:17: error write to a read-only table with key = fdsffalse input:17: error write to a read-only table with key = 2false input:17: error write to a read-only table with key = nilfalse input:17: error write to a read-only table with key = nilfalse input:17: error write to a read-only table with key = 3===pairs t3: e string===pairs t3: b table: 0x20ccd60===pairs t3: a table: 0x20d4e70===pairs t3: d 45===pairs t3: c table: 0x20ca700===pairs t3.a: 1 456===pairs t3.a: 2 89===ipair t3.a 1 456===ipair t3.a 2 89len t3: 0len t3.a: 2table: 0x20d4870 table: 0x20d4870table: 0x20d5690 table: 0x20d5690 table: 0x20d1140代码思路设计:
1.使用proxy={}空表而不是目标表tbl来设置__newindex是因为__newindex必须在原表里面不存在才会调用,这样就依然可以对已存在的字段进行改写
2.避免出现table的互相引用,加入travelled_tables存储已经设置过proxy的table的映射
3.对于原表tbl的访问使用__index=tbl
4.对于表查长度使用__len= function () return #tbl end
5.对于遍历pairs,查到lua5.3的pairs默认迭代器next不支持访问元表__index,故直接__pairs = function () return pairs(tbl) end,以此来生成对目标表的迭代遍历
6.对于ipairs,查到lua5.3 ipairs函数生成的迭代器默认就支持访问元表__index,故不需要添加__ipairs
8.2 – Changes in the Libraries
•The ipairs iterator now respects metamethods and its __ipairs metamethod has been deprecated.
7.对于table.insert , table.remove不用特殊处理,lua5.3的table lib支持元表操作,故依然会抛错
8.2 – Changes in the Libraries
•The Table library now respects metamethods for setting and getting elements.
8.避免重复创建read_only,每个tbl只创建一个proxy代理,在tbl的metatable里和proxy的metatable里都设置属性__read_only_proxy,可以直接访问获得
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
1.数组操作:在Lua中,“数组”只是table的一个别名,是指以一种特殊的方法来使用table。出于性能原因,Lua的CAPI为数组操作提供了专门的函数,如:
前言最近在尝试配置awesomeWM,因此粗略地学习了一下lua。在学习过程中,我完全被table在lua中的应用所镇住了。table在lua中真的是无处不在:
一.tabletable是lua唯一的数据结构。table是lua中最重要的数据类型。table类似于python中的字典。table只能通过构造式来创建。其他
判断方法结论:复制代码代码如下:a={}ifnext(a)~=nilthendosomethingend最近在项目里面大量使用的lua,其中lua的table是
Lua中metatable是一个普通的table,但其主要有以下几个功能:1.定义算术操作符和关系操作符的行为2.为Lua函数库提供支持3.控制对table的访