錯誤處理 Error Handling
8.6 defer語法可以讓程式碼更簡潔 Clearing Up Using defer
本小節內容比較簡單,主要延續之前的檔案的有效性查詢的Demo來引出defer語法,並介紹一些相關特性
引出defer關鍵字: 一般在可能丟擲異常的方法都會使用 try/finally結構。無論最後是否有丟擲異常都會走finally流程。 這個時候我們就可以使用defer語法讓程式碼變得更靈活
。
defer關鍵字的作用:實際是一個閉包
,在當前宣告的作用域結束時執行
。
defer在檔案讀寫中的使用.
func contents(ofFile ?lename: String) throws -> String {
let file = open("test.txt", O_RDONLY)
defer { close(file) }
let contents = try process(file: file)
return contents
}
複製程式碼
注1:在上面的demo中,如果不用defer關鍵字 當出現異常
,直接就try 提前結束了. 導致當前的檔案流沒有執行close方法。這個在以後的資料庫操作中可算是一個重大bug
。
注2: defer要寫在reture 前面
。 雖然它的執行上在return後。 你寫在return後面,程式碼編譯 return後的程式碼看都不看。這個時候你寫defer實際上沒啥用。
標準庫中對defer的使用
下面會寫出```Enumeratedlterator```協議中```next()```方法的程式碼實現。
##### 使用場景:增加計數器的值而且需要返回沒有增加值之前的值。
struct EnumeratedIterator<Base: IteratorProtocol>: IteratorProtocol, Sequence {
internal var _base: Base
internal var _count: Int ...
func next() -> Element? {
guard let b = _base.next() else { return nil }
defer { _count += 1 }
return (offset: _count, element: b)
}
}
複製程式碼
多defer方法多使用注意
寫一個運算元據庫的Demo來講講
guard let database = openDatabase(...) else { return }
defer { closeDatabase(database) }
guard let connection = openConnection(database) else { return }
defer { closeConnection(connection) }
guard let result = runQuery(connection, ...) else { return }
複製程式碼
類似於壓棧操作
,前面的後執行,後面的先執行。
上面的demo中的順序也是在執行完資料庫查詢之後先```關閉連結```,再去```關閉資料庫```。
複製程式碼
over~