或许这只是 LUA 的一种惯用法而已
2019年01月18日,同事指着 KONG 的一份源码问我,老黄,你知道他们为什么要这么写代码么,我瞅过去,看到了如下代码:
local get_upstream_by_id do ------------------------------------------------------------------------------ -- Loads a single upstream entity. -- @param upstream_id string -- @return the upstream table, or nil+error local function load_upstream_into_memory(upstream_id) log(DEBUG, "fetching upstream: ", tostring(upstream_id)) local upstream, err = singletons.db.upstreams:select({id = upstream_id}) if not upstream then return nil, err end return upstream end _load_upstream_into_memory = load_upstream_into_memory get_upstream_by_id = function(upstream_id) local upstream_cache_key = "balancer:upstreams:" .. upstream_id return singletons.cache:get(upstream_cache_key, nil, load_upstream_into_memory, upstream_id) end end
他迷惑的是,为啥要写成这种 local xx do ... end
的格式。而且就上面这段代码来说,完全可以直接写成这样:
------------------------------------------------------------------------------ -- Loads a single upstream entity. -- @param upstream_id string -- @return the upstream table, or nil+error local function load_upstream_into_memory(upstream_id) log(DEBUG, "fetching upstream: ", tostring(upstream_id)) local upstream, err = singletons.db.upstreams:select({id = upstream_id}) if not upstream then return nil, err end return upstream end _load_upstream_into_memory = load_upstream_into_memory local get_upstream_by_id = function(upstream_id) local upstream_cache_key = "balancer:upstreams:" .. upstream_id return singletons.cache:get(upstream_cache_key, nil, load_upstream_into_memory, upstream_id) end
前后两段从语义上并无二致。
因为单从 lua 的 do end 语法来看,do end 只是限定了本地变量的作用域,do end 内部定义的 local 变量,出了作用域就无法直接访问了(除了被闭包引用之外)。
从网络搜索,也基本印证这种说法:
问题是,刚开始的那段代码中的 do end 块中,并没有定义 local 变量啊,为啥还要这么写呢,我想,估计作者就是喜欢按照这个套路来,或者最早的代码中在do end中有local变量,或者后续代码功能增强或者重构后,也可能产生新的 local 变量,这样子 do end 的代码结构还可以保持不变。例如
local get_upstream_by_id do local xx local yy -- ... end
只能说作者学了 do end 的一招鲜了,不管是不是有用,都套上一把。跟那种写JAVA,有的同学总是在方法开头声明所有变量一样,有点相同的意味。
We can delimit a block explicitly, bracketing it with the keywords do-end. These do blocks can be useful when you need finer control over the scope of one or more local variables:
do local a2 = 2*a local d = sqrt(b^2 - 4*a*c) x1 = (-b + d)/a2 x2 = (-b - d)/a2 end -- scope of `a2' and `d' ends here print(x1, x2)
At times it is useful to further limit the scope of local variables with do-blocks [PIL 4.2]:
local v do local x = u2*v3-u3*v2 local y = u3*v1-u1*v3 local z = u1*v2-u2*v1 v = {x,y,z} end local count do local x = 0 count = function() x = x + 1; return x end end
Global variables scope can be reduced as well via the Lua module system [PIL2 15] or [setfenv].
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论