故事背景,我们为了我减轻数据库压力,做了一个内存数据,为了减少保存的量,需要做只保存有修改的字段,因为我们是lua语言。我们不想自己写修改标记,想系统自动判断表是否有被修改。
直接ai写的一个,看例子是可以用,实际要用了才知道。
local function createMonitoredTable(originalTable)
-- 独立存储代理状态(不污染原表)
local monitor = {
modified = false,
proxies = {} -- 缓存已代理的表,避免循环引用
}
-- 递归创建代理
local function createProxy(t)
-- 如果已经代理过,直接返回
if monitor.proxies[t] then
return monitor.proxies[t]
end
-- 创建代理表
local proxy = {}
monitor.proxies[t] = proxy -- 缓存代理
-- 设置代理的元表
setmetatable(proxy, {
__index = t,
__newindex = function(_, k, v)
-- 如果新值是 table,递归代理它
if type(v) == "table" then
v = createProxy(v)
end
-- 标记修改
monitor.modified = true
t[k] = v -- 修改原表(代理只是监听,实际数据仍在原表)
end
})
return proxy
end
-- 创建顶层代理
local proxy = createProxy(originalTable)
return {
-- 获取代理表(推荐所有操作都通过它)
getProxy = function() return proxy end,
-- 检查是否被修改
isModified = function() return monitor.modified end,
-- 重置修改标记
resetModified = function() monitor.modified = false end,
-- 获取原始表(直接修改可能绕过检测,慎用!)
getOriginal = function() return originalTable end
}
end
local original = { a = 1, b = { x = 10 } }
local monitored = createMonitoredTable(original)
local proxy = monitored.getProxy()
-- 方式1:通过代理修改(会被检测)
proxy.c = 3
proxy.b.y = 20
print(monitored.isModified()) --> true
monitored.resetModified()
-- 方式2:直接修改原表(也会被检测,因为子表已被代理)
original.d = 4
original.b.z = 30
print(monitored.isModified()) --> true
-- 查看最终数据
print(original.c) --> 3
print(original.d) --> 4
print(original.b.y) --> 20
print(original.b.z) --> 30