项目中部分只读表易被人误改写,故决定在非线上环境里对这些表附加只读属性,方便在出现误改写的时候抛出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=t1 local t3 = read_only(t1) print(t3.d, t3.c.e, t3.c.c.b.t2.fdsf) function q1() t3.d = 4555 end function q2() t3.c.d = 90 end function q3() t3.c.c.b.t2.fdsf =90 end function q4() table.remove(t3.a) end function q5() t3.b[ddss] = nil end function q6() t3[f] = 89 end function q7() table.insert(t3.a, 999) end print(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) end for k,v in pairs(t3.a) do print("===pairs t3.a:",k,v) end for k,v in ipairs(t3) do print("===ipairs t3:",k,v) end for k,v in ipairs(t3.a) do print("===ipair t3.a",k,v) end print("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: 0x20d4ba0 false input:17: error write to a read-only table with key = d false input:17: error write to a read-only table with key = d false input:17: error write to a read-only table with key = fdsf false input:17: error write to a read-only table with key = 2 false input:17: error write to a read-only table with key = nil false input:17: error write to a read-only table with key = nil false 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 89 len t3: 0 len t3.a: 2 table: 0x20d4870 table: 0x20d4870 table: 0x20d5690 table: 0x20d5690 table: 0x20d1140
代码思路设计:
1.使用proxy={}
空表而不是目标表tbl来设置__newindex是因为__newindex必须在原表里面不存在才会调用,这样就依然可以对已存在的字段进行改写
__newindex: The indexing assignment table[key] = value. Like the index event, this event happens when table is not a table or when key is not present in table. The metamethod is looked up in table. Like with indexing, the metamethod for this event can be either a function or a table. If it is a function, it is called with table, key, and value as arguments. If it is a table, Lua does an indexing assignment to this table with the same key and value. (This assignment is regular, not raw, and therefore can trigger another metamethod.) Whenever there is a __newindex metamethod, Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.)
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
"color: #ff0000">总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]