這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
原創文章。轉載請註明出處:server非業餘研究-sunface
近期看Googlego group裡面有非常多討論go error處理風格的問題,頗有啟示。如今跟大家分享一下。首先請看一個提問:
Hi folks,
When I look at a lot of go code, I see the following pattern://當我看了很多go代碼後,我發現了下面模式
x, err := foo()if err != nil {
return err
}
y, err := bar(x)if err != nil {
return err
}
z, err := baz(y)if err != nil {
return err
}
// do something w/ z
return nil
This is cool, but comes off as a bit verbose. I've been using the following as a replacement, which I think is a bit nicer://上段代碼非常cool,可是表現的有點冗餘。我已經用下面一種error機製作為替代。我覺得我的更好
var (
x, y, z T
err error
)
x, err = foo()
if err == nil {
y, err = bar(x)
}
if err == nil {
z, err = baz(y)
}
if err == nil {
// do something w/ z
}
return err
//出於好奇。請問有人用過我這樣的風格然後有發現過缺點嗎?或者這樣的風格並不好?儘管我覺得非常好
Just curious, has anyone else used this sort of thing and found a pitfall? Or perhaps has an opinion as to why it isn't actually nice?
I think it's nice =].
看了上面兩種錯誤處理風格。大家應該已經看出了部分端倪:第一種是比較傳統的error處理方式,另外一種是作者覺得比較創新的error處理方式。
先不說第一種的優缺點,
另外一種首先在開頭設定了全部接收error的變數。然後後面的error處理方式是環環相扣,冗餘度很之高。且直到最後才return,也就是說假設代碼夠長。那你得看完中間全部的處理過程。在這裡你僅僅有讀完了整段代碼才知道foo()產生的錯誤究竟是怎麼處理的。
然後一個評論中提出了一種個人認為不錯的風格:
value,err := bar()
if err != nil {
goto handleError
}
.
.
.
.
handleError:
return err
在這樣的風格中不須要去知道goto和label中間的代碼。能夠直接進行錯誤處理並返回,因此代碼簡潔、可讀性強、效能高且冗餘度低。
另一個評論提出了一種非常特別的風格:
if x, err := foo(); err != nil {
return err
} else if y, err := bar(x); err != nil {
return err
} else if z, err := baz(y); err != nil {
return err
} else {
// do something w/ x,y,z
return nil
}
這樣的寫法的代碼比較簡潔,return的地方一眼便可得知。
以下這樣的風格能夠節省大量的if語句
func checkErr( err error) {
if err != nil {
//deal error here
}
}
func main() {
ting,err := whatever()
checkErr(err)
}
以下再說說我個人對提問中第二段代碼的看法,主要有3點:
1.在第二段代碼中,全部的有意義的代碼都是環環相扣,每個if和return都要記在腦袋裡,詳細能夠看下這篇文章:代碼的嵌套——各種狀態的組合。在第一段代碼中全部的錯誤處理都是在產生錯誤碼的以下,非常easy發現什麼代碼導致了某個錯誤。並且在那些if代碼塊之後。你不須要操心之前的x,y,z。由於它們都是合法的。可是在第二段代碼中,永遠不能知道x,y,z是否合法,每次都得繼續驗證前面的值。
2.由於第二段代碼的錯誤處理和返回方式(環環相扣),我們就無法得知error的詳細位置,唯一能做的就是徹底放棄然後無奈的說一句“代碼有BUG了”,僅此而已。
3.每次你往第二段代碼的函數添加新的代碼的時候,都要放在一個if代碼快中。相反在第一段代碼中,就不須要,由於僅僅有錯誤處理在if中。其它的都在外部處理
這裡僅僅是一個簡單的拋磚引玉。希望大家能發表下尋常項目中使用的錯誤處理機制,一起討論。