0Pricing
Lua Academy · 课时

使用 __gc 执行终结操作

注册 __gc 元方法,在对象被回收时执行清理。

使用 __gc 执行终结操作 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。

什么是终结器?

终结器是垃圾回收器在对象释放前调用的函数。在 Lua 中,它通过表的元表上的 __gc 元方法实现。

设置终结器

在对象创建之前或创建时,将 __gc 函数附加到元表。

local mt = {
  __gc = function(self)
    print("Finalizing:", self.name)
  end
}
do
  local obj = setmetatable({name = "resource"}, mt)
end
collectgarbage()  -- prints: Finalizing: resource

资源清理模式

终结器非常适合释放外部资源,例如文件句柄、数据库连接或 C 内存。

local function openResource(path)
  local f = io.open(path, "r")
  return setmetatable({handle = f, path = path}, {
    __gc = function(self)
      if self.handle then
        self.handle:close()
        print("Closed:", self.path)
      end
    end
  })
end

终结器顺序

带有终结器的对象会按照创建顺序的逆序被回收。默认情况下,每个垃圾回收周期运行一个终结器。

对象复活

如果终结器将对象的引用保存到全局变量或上值中,对象就会被复活。对象最终被回收时,只会再获得一次终结器调用。

用户数据与 __gc

在 C 扩展中,用户数据上的 __gc 是释放 C 内存的主要方式。对于纯 Lua 代码,表通过元表使用相同的机制。

用于 RAII 的代理对象

创建一个代理表,让其 __gc 关闭真正的资源。这是在 C++ 中对 RAII 的模拟。

local function scoped(resource, cleanup)
  return setmetatable({resource}, {
    __gc = function(self) cleanup(self[1]) end
  })
end

终结器的局限

终结器不应执行协程操作、让出执行权,也不应假设其他对象仍存活的顺序。请保持终结器简单且简短。

弱表与终结器

弱表中的对象仍然可以执行终结。终结之后(以及可能发生的复活之后),它们会在下一轮中被完全回收。

toLua 终结器保护

在终结器内部使用布尔标志,以防对象复活时发生重复清理。

local mt = {}
mt.__gc = function(self)
  if not self._closed then
    self._closed = true
    -- cleanup...
  end
end

实用建议

优先使用明确的 :close() 或 :destroy() 方法,以便确定性地完成清理。请将 __gc 作为意外遗漏时的安全保障,而不是主要的资源管理方式。

终结器问题

__gc 元方法何时被调用?

回顾:使用 __gc 的终结器

__gc 元方法会在对象即将被回收前运行,从而支持类似 RAII 的资源清理。请将它作为安全保障;对于确定性的资源管理,应优先使用明确的关闭或销毁方法。

常见问题解答

「使用 __gc 执行终结操作」课时是免费的吗?

是的 — 「使用 __gc 执行终结操作」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「使用 __gc 执行终结操作」这节课中我会学到什么?

注册 __gc 元方法,在对象被回收时执行清理。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「使用 __gc 执行终结操作」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Lua 垃圾回收基础
  2. 弱键和弱值
  3. 使用 __gc 执行终结操作
  4. 避免内存泄漏
← 返回 Lua Academy