闽公网安备 35020302035485号
func safeMethod() {
lock.lock()
defer {
lock.unlock()
}
// 执行需要同步的代码
// 如果这里有 return 或抛出异常,defer 仍然保证锁被释放
}
2. 数据库操作func updateDatabase() {
let connection = database.connect()
defer {
connection.close()
}
// 堆代码 duidaima.com
// 执行数据库更新操作
// 不管操作成功还是失败,连接都会被关闭
}
3. 文件处理func processFile(path: String) throws {
let file = try FileHandle(forReadingFrom: URL(fileURLWithPath: path))
defer {
file.closeFile()
}
// 读取并处理文件内容
}
实现原理#ifndef SWIFT_BASIC_DEFER_H
#define SWIFT_BASIC_DEFER_H
#include "llvm/ADT/ScopeExit.h"
namespace swift {
namespace detail {
struct DeferTask {};
template<typename F>
auto operator+(DeferTask, F &&fn) ->
decltype(llvm::make_scope_exit(std::forward<F>(fn))) {
return llvm::make_scope_exit(std::forward<F>(fn));
}
}
}
#define DEFER_CONCAT_IMPL(x, y) x##y
#define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y)
#define SWIFT_DEFER \
auto DEFER_MACRO_CONCAT(defer_func, __COUNTER__) = \
::swift::detail::DeferTask() + [&]()
#endif // SWIFT_BASIC_DEFER_H
这段代码是用 C++ 写的,但它揭示了 defer 的核心机制。简单解释一下上边的代码:然后,它创建了一个 swift::detail::DeferTask 的实例,并使用+操作符重载将其与一个 lambda 表达式相加。这个 lambda 表达式是在SWIFT_DEFER 宏后面的代码块中定义的,它是在作用域结束时需要执行的代码。
这个返回的对象被赋值给了一个局部变量,当这个局部变量的作用域结束时(即离开 SWIFT_DEFER 所在的作用域时),它的析构函数会自动被调用,从而执行之前定义的 lambda 表达式。
func complexOperation() {
defer { print("清理操作 1") }
defer { print("清理操作 2") }
print("执行某些操作")
}
// 输出:
// 执行某些操作
// 清理操作 2
// 清理操作 1
2. 在 for 循环中使用for item in collection {
defer { print("处理 \(item)") }
if item.shouldSkip {
continue
}
// 处理项
}
在这个例子中,即使 continue 语句跳过了某些迭代,每个 defer 也都会在其对应的迭代结束时执行。func doSoming() {
defer {
print("doSoming")
}
}