问题的背景:
defer被引入到Swift中(受到Go、C#等的启发),以确保在发生错误、退出函数或从函数的不同点返回值时,资源能够被清理。
问题:
提早释放、遗忘清理资源(例如,关闭文件、日志记录、事务回滚)。有时人们混淆了执行顺序,错误地认为defer在声明时就会执行。
解决方案:
defer是一个特殊的代码块,它会延迟执行直到当前作用域(scope)的结束,通常是函数的结束。所有defer按逆序执行(LIFO)。这使得能够集中管理资源的清理、内存的释放或事务的回滚。
代码示例:
func processFile() { let file = File("/tmp/data.txt") file.open() defer { file.close() print("文件已关闭") } // 与文件的操作 print("读取数据…") }
关键特点:
如果应用程序在退出函数之前崩溃(defer)中的代码会执行吗?
不,defer中的代码只在正常退出作用域时执行。如果应用程序崩溃(例如,fatal error),defer将不会执行。
可以在defer中使用return吗?
不可以。defer块不允许返回值或结束作用域,只允许指令。
defer可以用于修改在defer之前声明的变量吗?
可以,defer会捕获执行时当前栈的值。在defer之前声明的值可以被修改,并且在退出scope时会保留这些修改。
代码示例:
func example() -> Int { var result = 0 defer { result = 42 } return result // defer将执行,结果为42 }
文件打开了,但只在函数的底部显式关闭,而在错误或提前退出函数时,文件保持打开状态。
优点:
缺点:
在打开文件后立即使用defer来关闭文件。即使发生异常或从函数返回,文件也能得到保证关闭。
优点:
缺点: