或许这只是 LUA 的一种惯用法而已

发布于 2022-09-22 22:35:46 字数 3369 浏览 5 评论 0

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

列表为空,暂无数据

关于作者

凑诗

暂无简介

0 文章
0 评论
0 人气
更多

推荐作者

淹不死的鱼

文章 0 评论 0

zhangMack

文章 0 评论 0

爱的故事

文章 0 评论 0

linces

文章 0 评论 0

早乙女

文章 0 评论 0

鸵鸟症

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。