diff --git a/ch5/ch5-10.md b/ch5/ch5-10.md index 9ae4acd..5c09a41 100644 --- a/ch5/ch5-10.md +++ b/ch5/ch5-10.md @@ -1,10 +1,10 @@ ## 5.10. Recover捕獲異常 -通常来说,不应该对panic异常做任何处理,但有时,也许我们可以从异常中恢复,至少我们可以在程序崩溃前,做一些操作。举个例子,当web服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭;如果不做任何处理,会使得客户端一直处于等待状态。如果web服务器还在开发阶段,服务器甚至可以将异常信息反馈到客户端,帮助调试。 +通常來説,不應該對panic異常做任何處理,但有時,也許我們可以從異常中恢複,至少我們可以在程序崩潰前,做一些操作。舉個例子,當web服務器遇到不可預料的嚴重問題時,在崩潰前應該將所有的連接關閉;如果不做任何處理,會使得客戶端一直處於等待狀態。如果web服務器還在開發階段,服務器甚至可以將異常信息反饋到客戶端,幫助調試。 -如果在deferred函数中调用了内置函数recover,并且定义该defer语句的函数发生了panic异常,recover会使程序从panic中恢复,并返回panic value。导致panic异常的函数不会继续运行,但能正常返回。在未发生panic时调用recover,recover会返回nil。 +如果在deferred函數中調用了內置函數recover,併且定義該defer語句的函數發生了panic異常,recover會使程序從panic中恢複,併返迴panic value。導致panic異常的函數不會繼續運行,但能正常返迴。在未發生panic時調用recover,recover會返迴nil。 -让我们以语言解析器为例,说明recover的使用场景。考虑到语言解析器的复杂性,即使某个语言解析器目前工作正常,也无法肯定它没有漏洞。因此,当某个异常出现时,我们不会选择让解析器崩溃,而是会将panic异常当作普通的解析错误,并附加额外信息提醒用户报告此错误。 +讓我們以語言解析器爲例,説明recover的使用場景。考慮到語言解析器的複雜性,卽使某個語言解析器目前工作正常,也無法肯定它沒有漏洞。因此,當某個異常出現時,我們不會選擇讓解析器崩潰,而是會將panic異常當作普通的解析錯誤,併附加額外信息提醒用戶報告此錯誤。 ```Go func Parse(input string) (s *Syntax, err error) { @@ -17,17 +17,17 @@ func Parse(input string) (s *Syntax, err error) { } ``` -deferred函数帮助Parse从panic中恢复。在deferred函数内部,panic value被附加到错误信息中;并用err变量接收错误信息,返回给调用者。我们也可以通过调用runtime.Stack往错误信息中添加完整的堆栈调用信息。 +deferred函數幫助Parse從panic中恢複。在deferred函數內部,panic value被附加到錯誤信息中;併用err變量接收錯誤信息,返迴給調用者。我們也可以通過調用runtime.Stack往錯誤信息中添加完整的堆棧調用信息。 -不加区分的恢复所有的panic异常,不是可取的做法;因为在panic之后,无法保证包级变量的状态仍然和我们预期一致。比如,对数据结构的一次重要更新没有被完整完成、文件或者网络连接没有被关闭、获得的锁没有被释放。此外,如果写日志时产生的panic被不加区分的恢复,可能会导致漏洞被忽略。 +不加區分的恢複所有的panic異常,不是可取的做法;因爲在panic之後,無法保證包級變量的狀態仍然和我們預期一致。比如,對數據結構的一次重要更新沒有被完整完成、文件或者網絡連接沒有被關閉、獲得的鎖沒有被釋放。此外,如果寫日誌時産生的panic被不加區分的恢複,可能會導致漏洞被忽略。 -虽然把对panic的处理都集中在一个包下,有助于简化对复杂和不可以预料问题的处理,但作为被广泛遵守的规范,你不应该试图去恢复其他包引起的panic。公有的API应该将函数的运行失败作为error返回,而不是panic。同样的,你也不应该恢复一个由他人开发的函数引起的panic,比如说调用者传入的回调函数,因为你无法确保这样做是安全的。 +雖然把對panic的處理都集中在一個包下,有助於簡化對複雜和不可以預料問題的處理,但作爲被廣泛遵守的規范,你不應該試圖去恢複其他包引起的panic。公有的API應該將函數的運行失敗作爲error返迴,而不是panic。同樣的,你也不應該恢複一個由他人開發的函數引起的panic,比如説調用者傳入的迴調函數,因爲你無法確保這樣做是安全的。 -有时我们很难完全遵循规范,举个例子,net/http包中提供了一个web服务器,将收到的请求分发给用户提供的处理函数。很显然,我们不能因为某个处理函数引发的panic异常,杀掉整个进程;web服务器遇到处理函数导致的panic时会调用recover,输出堆栈信息,继续运行。这样的做法在实践中很便捷,但也会引起资源泄漏,或是因为recover操作,导致其他问题。 +有時我們很難完全遵循規范,舉個例子,net/http包中提供了一個web服務器,將收到的請求分發給用戶提供的處理函數。很顯然,我們不能因爲某個處理函數引發的panic異常,殺掉整個進程;web服務器遇到處理函數導致的panic時會調用recover,輸出堆棧信息,繼續運行。這樣的做法在實踐中很便捷,但也會引起資源洩漏,或是因爲recover操作,導致其他問題。 -基于以上原因,安全的做法是有选择性的recover。换句话说,只恢复应该被恢复的panic异常,此外,这些异常所占的比例应该尽可能的低。为了标识某个panic是否应该被恢复,我们可以将panic value设置成特殊类型。在recover时对panic value进行检查,如果发现panic value是特殊类型,就将这个panic作为errror处理,如果不是,则按照正常的panic进行处理(在下面的例子中,我们会看到这种方式)。 +基於以上原因,安全的做法是有選擇性的recover。換句話説,隻恢複應該被恢複的panic異常,此外,這些異常所占的比例應該盡可能的低。爲了標識某個panic是否應該被恢複,我們可以將panic value設置成特殊類型。在recover時對panic value進行檢査,如果發現panic value是特殊類型,就將這個panic作爲errror處理,如果不是,則按照正常的panic進行處理(在下面的例子中,我們會看到這種方式)。 -下面的例子是title函数的变形,如果HTML页面包含多个`