2016-09-22 82 views
3

我最近進入了Go,並且看到了很多關於如何進行錯誤處理的討論。Golang idomatic嵌套錯誤處理

我所看到的佈局模式如下:

err := DoSomething() 
if err != nil { 
    //handle 
} 
// continue 

很多時候,管理AMQP連接時,我的條件是,我想如果誤差爲零繼續,因爲那時我需要做連接的東西:

c, err := Connect() 
if err != nil { 
    return nil, err 
} 
s,err := c.RegisterSomethingOnConnection() 
if err != nil { 
    return nil, err 
} 
val, err := s.DoSomething() 
return val, err 

,你可以看到我只想運行線c.RegisterSomethingOnConnection如果從Connect()返回的錯誤是零。

不過,我不喜歡上面由於前期收益。早期回報讓我感到不舒服,因爲從長遠來看,它會傷害可讀性,並在函數退出時模糊不清。到目前爲止,我的解決方案一直在執行以下操作:

var err error 
var val ReturnType 

c,err := Connect() 
if err == nil { 
    s,err := c.RegisterSomethingOnConnection() 
    if err == nil { 
     val,err = s.DoSomething() 
    } 
} 
return val,err 

我喜歡這樣做,原因有兩個。首先,它防止返回零。其次,我發現它使代碼更易於維護,因爲您可以在返回之前輕鬆添加功能(即記錄),並且不會由於提前返回而導致某些路徑錯過附加功能。

是我做了什麼接受習慣去還是我只需要得到超過我的早期回報的厭惡,並按照這個模式?

+1

可能重複的[Go。最佳實踐來處理多個抽象層次的錯誤](http://stackoverflow.com/questions/37346694/go-best-practice-to-handle-error-from-multiple-abstract-level) – icza

回答

3

一個圍棋證明者是:

不要只檢查錯誤,妥善處理他們

我建議你閱讀本post來自Dave Cheney

我把這裏的亮點:

「沒有單一的方法來處理錯誤。相反,我相信Go的錯誤處理可分爲三大核心戰略「

  • 哨兵錯誤:

if err == ErrSomething { … }

」使用哨兵值是最靈活的錯誤處理策略,因爲調用者必須使用相等運算符將結果與預先聲明的值進行比較。當你想提供更多的背景下,作爲返回不同的錯誤會會打破平等檢查這提出了一個問題。「

  • 錯誤類型

if err, ok := err.(SomeType); ok { … }

」錯誤類型是您創建的實現錯誤界面的類型。 「

  • 不透明錯誤

x, err := bar.Foo() if err != nil { return err } // use x

」我把這種風格不透明的錯誤處理,因爲一會兒你就知道發生了錯誤,你沒有看到裏面的能力錯誤。作爲主叫方,你知道操作的結果是,它的工作,或者沒有。」

....閱讀所有文章。

我認爲錯誤的重要方面處理是不要只是檢查錯誤,妥善處理它們,我希望這可以幫到你

+0

謝謝,這篇文章非常有幫助,如果我對它有正確的理解,可以如果用其他上下文包裝並僅將其記錄在一個地方,則返回錯誤,對嗎? – Fuzzerker

+0

@Fuzzerker我認爲是正確的,錯誤是爲人類而不是代碼。 –

+0

@Fuzzerker我喜歡這種方式,'返回fmt.Errorf(「驗證失敗:%v」,錯誤)'不要錯過錯誤發生的地方。 –

1

Go. Best practice to handle error from multiple abstract level

您應該處理錯誤,或者不處理它,但它委託給 一個更高的水平(給調用者)。處理錯誤並返回錯誤 不好的做法就好像調用者也是一樣,錯誤可能會得到 多次處理。

而看到:
Errors are Values羅布派克。

Go Error Handling Techniques


你可以把它簡化:

if err := datastore.Get(c, key, record); err != nil { 

簡化重複性的錯誤處理:

在圍棋,錯誤處理是很重要的。語言的設計和 公約鼓勵你明確地檢查錯誤,其中 出現時(從拋出 異常的其他語言的慣例截然不同,有時趕上他們)。在某些情況下,這會使代碼變得冗長,但幸運的是,有一些技巧可以用來減少重複的錯誤處理。

考慮與檢索 一個從數據存儲和格式它與一個模板記錄的HTTP處理程序的App Engine應用程序。

func init() { 
    http.HandleFunc("/view", viewRecord) 
} 

func viewRecord(w http.ResponseWriter, r *http.Request) { 
    c := appengine.NewContext(r) 
    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil) 
    record := new(Record) 
    if err := datastore.Get(c, key, record); err != nil { 
     http.Error(w, err.Error(), 500) 
     return 
    } 
    if err := viewTemplate.Execute(w, record); err != nil { 
     http.Error(w, err.Error(), 500) 
    } 
} 

參見:https://blog.golang.org/error-handling-and-go