美文网首页
Lua 闭包(Closure)

Lua 闭包(Closure)

作者: 香菜香菜我是折耳根 | 来源:发表于2020-09-07 17:53 被阅读0次

今天看到一个非常生动的使用闭包概念的代码片段,决定记录下来,这个代码出自 Kong 的插件 rate-limiting :

function RateLimitingHandler:access(conf)
  -- ...

  kong.ctx.plugin.timer = function()
    local ok, err = timer_at(0, increment, conf, limits, identifier, current_timestamp, 1)
    if not ok then
      kong.log.err("failed to create timer: ", err)
    end
  end
end

function RateLimitingHandler:log(_)
  if kong.ctx.plugin.timer then
    kong.ctx.plugin.timer()
  end
end

在学习闭包概念的时候,对里面提到的一句话不是非常理解:闭包可以捕捉作用域内的变量。一直没有找到特别好的实际用例,在这个代码片段里就能比较清晰的理解了。 access 阶段声明了一个延时函数的闭包,这个闭包在 log 阶段进行调用。如果不用闭包的话,代码会是什么样子呢?

function RateLimitingHandler:access(conf)
  -- ...

  kong.ctx.plugin.limits = limits
  kong.ctx.plugin.identifier = identifier
  kong.ctx.plugin.timestamp = current_timestamp
end

function RateLimitingHandler:log(_)
  local limits = kong.ctx.plugin.limits
  local identifier = kong.ctx.plugin.identifier
  local current_timestamp = kong.ctx.plugin.timestamp

  local ok, err = timer_at(0, increment, conf, limits, identifier, current_timestamp, 1)
  if not ok then
    kong.log.err("failed to create timer: ", err)
  end
end

我们需要使用 kong.ctx.plugin 来在 access 和 log 阶段之间共享变量,这样代码会显得很臃肿,如果使用闭包进行作用域变量的捕捉,那么代码就会写得简洁优雅。

如何修改闭包内的变量?这里我依然引用 Kong 2.x 的插件代码,比方说我们要开发一个插件的 Admin API ,我们需要在插件目录下创建 api.lua :

local endpoints = require "kong.api.endpoints"

local kong = kong
local caches_schema = kong.db.caches.schema

return {
  ["/caches"] = {
    schema = caches_schema,
    methods = {
      GET = endpoints.get_collection_endpoint(caches_schema),
    },
  },
  ["/caches/:cache_id"] = {
    schema = caches_schema,
    methods = {
      GET = function(self, ...)
        self.params.devices = { id = self.params.id }
        return endpoints.get_entity_endpoint(caches_schema)(self, ...)
      end,
    },
  },
}

首先看下这里的 get_collection_endpointget_entity_endpoint 方法是什么东西( kong/api/endpoints.lua ):

local function get_entity_endpoint(schema, foreign_schema, foreign_field_name, method, is_foreign_entity_endpoint)
  return function(self, db, helpers)
    -- ...
  end
end

可以看到,这里其实是返回了一个闭包,那么我们该如何修改这个闭包的参数呢?就是创建一个外部的函数,在这个函数里调用这个闭包,从而修改:

GET = function(self, ...)
  self.params.caches = { id = self.params.id }
  return endpoints.get_entity_endpoint(caches_schema)(self, ...)
end,

相关文章

  • Lua 闭包(Closure)

    今天看到一个非常生动的使用闭包概念的代码片段,决定记录下来,这个代码出自 Kong 的插件 rate-limiti...

  • 关于rust中的闭包(一)

    闭包 在计算机中,闭包 Closure, 又称词法闭包 Lexical Closure 或函数闭包 functio...

  • 关于闭包

    闭包的英文是closure,又称词法闭包(Lexical Closure)和函数闭包(Function Closu...

  • 理解闭包

    闭包 何为闭包 闭包(Closure)是词法闭包(Lexical Closure)的缩写 高级程序设计中写有权访问...

  • python之闭包与装饰器

    1 闭包 维基百科给出的解析:闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭...

  • 闭包,定时器

    问题 1.什么是闭包? 有什么作用 闭包(英语:Closure),又称词法闭包(Lexical Closure)或...

  • [Code] 优雅地使用python闭包

    在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(funct...

  • golang:函数闭包

    From wiki 闭包在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure...

  • 理解Python闭包

    1.什么是闭包? 维基百科: 在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的...

  • Lua closure

    前言# “closure”,一个之前我从没见过的词出现在了lua的编程世界中,lua将其解释为闭包,它具有着这种特...

网友评论

      本文标题:Lua 闭包(Closure)

      本文链接:https://www.haomeiwen.com/subject/hkylektx.html