ch5-10 zh2tw

This commit is contained in:
D
2016-01-11 23:38:47 +08:00
parent 417f366e89
commit 5c288d0893

View File

@@ -1,10 +1,10 @@
## 5.10. Recover捕獲異常
通常来说,不应该对panic常做任何理,但有,也许我们可以从异常中恢,至少我可以在程序崩前,做一些操作。举个例子,web服器遇到不可料的严重问题时,在崩溃前应该将所有的连接关闭;如果不做任何理,使得客端一直处于等待状态。如果web服务器还在开发阶段,服器甚至可以将异常信息反到客端,帮助调试
通常來説,不應該對panic常做任何理,但有,也許我們可以從異常中恢,至少我可以在程序崩前,做一些操作。舉個例子,web服器遇到不可料的嚴重問題時,在崩潰前應該將所有的連接關閉;如果不做任何理,使得客端一直處於等待狀態。如果web服務器還在開發階段,服器甚至可以將異常信息反到客端,幫助調試
如果在deferred函数中调用了置函recover且定义该defer句的函数发生了panicrecover使程序panic中恢复,并返回panic value。致panic常的函数不会继续运行,但能正常返。在未生panic时调用recoverrecover会返回nil。
如果在deferred函數中調用了置函recover且定義該defer句的函數發生了panicrecover使程序panic中恢複,併返迴panic value。致panic常的函數不會繼續運行,但能正常返。在未生panic時調用recoverrecover會返迴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函数帮助Parsepanic中恢。在deferred函数内panic value被附加到错误信息中;用err量接收错误信息,返回给调用者。我也可以通过调用runtime.Stack往错误信息中添加完整的堆栈调用信息。
deferred函數幫助Parsepanic中恢。在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面包含多`<title>`该函数会给调用者返回一个错误error。在soleTitle内部处理时,如果检测到有多`<title>`会调用panic阻止函数继续递归,并将特殊型bailout作panic的参数
下面的例子是title函數的變如果HTML面包含多`<title>`該函數會給調用者返迴一個錯誤error。在soleTitle內部處理時,如果檢測到有多`<title>`會調用panic阻止函數繼續遞歸,併將特殊型bailout作panic的參數
```Go
// soleTitle returns the text of the first non-empty title element
@@ -61,8 +61,8 @@ func soleTitle(doc *html.Node) (title string, err error) {
}
```
在上例中deferred函数调用recover并检查panic value。panic value是bailout{}类型时deferred函生成一error返回给调用者。panic value是其他non-nil值,表示生了未知的panicdeferred函数将调用panic函数并将当前的panic value作为参数传入;此,等同recover有做任何操作。(请注意:在例子中,对可预期的错误采用了panic这违反了之前的建,我在此是想向者演示这种机制。)
在上例中deferred函數調用recover併檢査panic value。panic value是bailout{}類型時deferred函生成一error返迴給調用者。panic value是其他non-nil值,表示生了未知的panicdeferred函數將調用panic函數併將當前的panic value作爲參數傳入;此,等同recover有做任何操作。(請註意:在例子中,對可預期的錯誤采用了panic這違反了之前的建,我在此是想向者演示這種機製。)
有些情下,我们无法恢。某些致命错误会导致Go在运行时终止程序,如存不足。
有些情下,我們無法恢。某些致命錯誤會導致Go在運行時終止程序,如存不足。
**练习5.19** 使用panic和recover编写一个不包含return句但能返回一个非零值的函
**練習5.19** 使用panic和recover編寫一個不包含return句但能返迴一個非零值的函