16.10 糟糕的錯誤處理
依附於第13章模式的描述和第17.1小節與第17.2.4小節的總結。
16.10.1 不要使用布爾值:
像下面代碼一樣,創建一個布爾型變量用於測試錯誤條件是多餘的:
var good bool
// 測試一個錯誤,`good`被賦爲`true`或者`false`
if !good {
return errors.New("things aren’t good")
}
立即檢測一個錯誤:
... err1 := api.Func1()
if err1 != nil { … }
16.10.2 避免錯誤檢測使代碼變得混亂:
避免寫出這樣的代碼:
... err1 := api.Func1()
if err1 != nil {
fmt.Println("err: " + err.Error())
return
}
err2 := api.Func2()
if err2 != nil {
...
return
}
首先,包括在一個初始化的if
語句中對函數的調用。但即使代碼中到處都是以if
語句的形式通知錯誤(通過打印錯誤信息)。通過這種方式,很難分辨什麼是正常的程序邏輯,什麼是錯誤檢測或錯誤通知。還需注意的是,大部分代碼都是致力於錯誤的檢測。通常解決此問題的好辦法是儘可能以閉包的形式封裝你的錯誤檢測,例如下面的代碼:
func httpRequestHandler(w http.ResponseWriter, req *http.Request) {
err := func () error {
if req.Method != "GET" {
return errors.New("expected GET")
}
if input := parseInput(req); input != "command" {
return errors.New("malformed command")
}
// 可以在此進行其他的錯誤檢測
} ()
if err != nil {
w.WriteHeader(400)
io.WriteString(w, err)
return
}
doSomething() ...
這種方法可以很容易分辨出錯誤檢測、錯誤通知和正常的程序邏輯(更詳細的方式參考第13.5小節)。
在開始閱讀第17章前,先回答下列2個問題:
問題 16.1:總結你能記住的所有關於
,ok
模式的情況。問題 16.2:總結你能記住的所有關於
defer
模式的情況。