运算符**defer**延迟执行代码,直到退出当前作用域,通常是从函数中返回。它方便用于清理资源、关闭文件和释放内存——即所谓的自动清理。
特点:
示例:
func processFile() { let file = openFile() defer { closeFile(file) } // 处理文件 // 即使在throw或return情况下,file也会被关闭 }
**非典型用法:**部分模拟'finally'类型的结构,代码分组以进行日志记录和跟踪运行时间。
如果应用程序在执行函数过程中结束,defer会执行吗?
— 不会。Defer仅在正常结束作用域时执行(return、throw或正常退出)。如果应用程序异常终止(例如,由于SIGKILL信号或fatalError),defer块将无法执行。
示例:
func foo() { defer { print("清理") } fatalError("崩溃!") // defer不会执行 }
故事
一个与套接字打交道的函数在throw时没有清理连接。数据悬留,连接没有释放。引入defer后,一切正常:资源总是被关闭。
故事
开发人员试图依赖defer释放全局状态。发生fatalError时资源未释放,导致服务阻塞和需要重启。
故事
在函数中声明了几个defer,认为它们会按照声明顺序执行。结果,资源以错误的顺序关闭(例如,首先关闭了文件描述符,然后试图访问它)。解决方案:牢记defer块的LIFO执行顺序。