Swift Academy · 课时

defer、错误与提前返回

即使抛出错误或提前返回,也确保完成清理。

第 4 / 4 课13 个步骤

defer、错误与提前返回 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

延迟执行在返回时运行

即使函数通过 return 提前退出,defer 代码块仍会运行。

func check(_ value: Int) {
    defer { print("cleanup ran") }
    if value < 0 {
        print("negative, returning early")
        return
    }
    print("value is", value)
}
check(-5)

每条路径都会清理

无论哪个 return 被执行,延迟清理都会准确运行一次。

func classify(_ n: Int) {
    defer { print("done classifying") }
    if n == 0 { print("zero"); return }
    if n > 0 { print("positive"); return }
    print("negative")
}
classify(0)

延迟执行在抛出错误时运行

函数抛出错误时,已注册的延迟执行仍会在作用域展开退出的过程中运行。

enum MyError: Error { case bad }
func risky(_ fail: Bool) throws {
    defer { print("cleanup on the way out") }
    if fail { throw MyError.bad }
    print("no failure")
}
try? risky(true)

结合返回与抛出错误

无论函数正常返回还是抛出错误,同一个延迟执行都会运行。

enum E: Error { case oops }
func op(_ flag: Bool) throws -> Int {
    defer { print("op finishing") }
    if flag { throw E.oops }
    return 42
}
let r = try? op(false)
print(r ?? -1)

错误传播前进行清理

延迟执行会在抛出的错误到达调用者之前运行,因此资源会先被释放。

enum E: Error { case fail }
func load(_ broken: Bool) throws {
    print("open")
    defer { print("close") }
    if broken { throw E.fail }
    print("read")
}
do {
    try load(true)
} catch {
    print("caught:", error)
}

使用延迟执行保护

一种常见模式是:获取资源、延迟执行清理,然后使用 guard 提前返回;这些提前返回仍会触发清理。

func process(_ items: [Int]) {
    print("start")
    defer { print("finished") }
    guard !items.isEmpty else {
        print("nothing to do")
        return
    }
    print("processing", items.count, "items")
}
process([])

延迟执行与抛出错误的循环

循环中的延迟执行会在每次迭代结束时运行,即使后面的语句抛出了错误。

enum E: Error { case stop }
func loop() throws {
    for i in 1...3 {
        defer { print("end", i) }
        if i == 2 { throw E.stop }
        print("body", i)
    }
}
try? loop()

提前返回时的顺序

提前返回时,多个延迟执行仍会按 LIFO 顺序运行。

func multi(_ skip: Bool) {
    defer { print("A") }
    defer { print("B") }
    if skip { return }
    print("body")
}
multi(true)

失败时记录日志

使用延迟执行,可以在所有退出路径上统一记录完成或失败信息。

enum E: Error { case bad }
func attempt(_ fail: Bool) throws {
    var success = false
    defer { print("attempt success:", success) }
    if fail { throw E.bad }
    success = true
}
try? attempt(true)

抛出错误时恢复状态

操作抛出错误时,延迟执行非常适合回滚临时状态。

enum E: Error { case fail }
func transaction(_ fail: Bool) throws {
    var inProgress = true
    defer { inProgress = false; print("inProgress:", inProgress) }
    if fail { throw E.fail }
    print("committed")
}
try? transaction(true)

最佳实践

对于必须在提前返回和抛出错误后仍执行的清理,请依靠 defer,这样任何退出路径都不会造成资源泄漏。

enum E: Error { case x }
func safe(_ fail: Bool) throws {
    print("acquire")
    defer { print("release") }
    if fail { throw E.x }
    print("use")
}
try? safe(true)

快速检查

测试延迟执行在错误和返回情况下的行为。

回顾

defer 会在每次作用域退出时运行,包括提前执行 return 和抛出错误的情况,并且会在错误传播之前执行。这使它成为在所有退出路径上进行清理和恢复状态的可靠位置,同时保留 LIFO 顺序。

func f(_ skip: Bool) {
    defer { print("cleanup") }
    if skip { return }
    print("work")
}
f(true)
免费开始

用 AI 导师学习 Swift — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
122
课程
409

常见问题解答

「defer、错误与提前返回」课时是免费的吗?

是的 — 「defer、错误与提前返回」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「defer、错误与提前返回」这节课中我会学到什么?

即使抛出错误或提前返回,也确保完成清理。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

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

「defer、错误与提前返回」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. defer 的工作原理
  2. 多个 defer 代码块的执行顺序
  3. 使用 defer 清理资源
  4. defer、错误与提前返回
← 返回 Swift Academy