切換語言為:簡體
在 Go 中用 #err 識別符號去做錯誤處理?PASS!

在 Go 中用 #err 識別符號去做錯誤處理?PASS!

  • 爱糖宝
  • 2024-06-06
  • 2073
  • 0
  • 0

前幾天看 Reddit 社羣裡的討論,發現 Go 這一門程式語言,錯誤處理永遠是討論的議題之一。本著追蹤網友腦洞 Proposal 的基礎上,週末看到個被反對比較多的 Go2 錯誤處理提案。

在 Go 中用 #err 識別符號去做錯誤處理?PASS!

今天結合分享給大家,好的壞的都可以圍觀一下。

問題背景

在 Go 這門程式語言中,錯誤處理機制主要是依賴於 if err != nil 的方式。因此在對函式做一定的封裝後。

程式碼最終常呈現出以下樣子:

jy1, err := GetFoo()
if err != nil {
    return err
}
jy2, err := SliceTheBar(varFoo)
if err != nil {
    return err
}
err := CheckBarSlice(sliceBar)
if err != nil {
    return err
}
...

有部分開發者會認為這比較的醜陋、混亂且難以閱讀。

在 Go 中用 #err 識別符號去做錯誤處理?PASS!

有人戲稱一個 Go 工程裡有 60% 的程式碼是 if err != nil,為此我見過直接用 panic 來做錯誤處理的團隊。

新提案:用 #err 作為識別符號

提案的提出者 @mainjzb,主要的設計目標是:# 作為錯誤符號,格式上將 #@ 作為處理程式錯誤符號。幫助開發者閱讀程式碼並簡化程式碼。

原本 Go 錯誤處理方式,如下老程式碼:

n, err := io.Write(x)
n, _ := io.Write(x) 

n, err := io.Write(x)
if err != nil {
   return 0, err
}

n, err := io.Write(x)
if err != nil {
   return 0, fmt.Error("tcp closed: %w", err)
}

n, err := io.Write(x)
if err != nil{
    panic(err)
}

使用上述提案後的錯誤標識改造後,新的程式碼如下:

// 1. err as value
n := io.Write(x) #err       

// 2. ignore error
n := io.Write(x) #@ignore   

//  3. return error immediately、
n := io.Write(x) #@done     

// 4. wrap additional information
n := io.Write(x) #@wrap("tcp closed: %w") 

// 5. panic err
n := io.Write(x) #@must

  1. #err 識別符號:err 變數作為值,一切與以前 error 一樣。只是變成了 #err 的標識用法。

  2. #@ignore 識別符號:使忽略錯誤變得比以前更易讀,也可以用附加的描述資訊便於開發者閱讀。

  3. #@done 識別符號:直接返回錯誤資訊。很多時候(特別是在庫中),只需要返回錯誤,無需執行任何操作。例如:url.parseAuthority

  4. #@wrap 識別符號:在 error 上附帶更多的錯誤資訊,例如:#@wrap 等於 #@wrap("io.Wirite err:")

  5. #@must 識別符號:這個識別符號可以在產生錯誤時,直接發生 panic 事件。

總結

這個提案的作者有多門程式語言經驗,本次提出的新提案,很明顯是瞄著解決 Go 這門程式語言中的 if err != nil 的不斷重複的程式碼內容的方向去的。

雖然原提案作者另闢蹊徑,透過增加 #err 這類識別符號來直接扭轉錯誤處理,解決了大量重複 err 程式碼。

在 Go 中用 #err 識別符號去做錯誤處理?PASS!

但最終與 Go 語言的其他部分過於不適。已經被 ban 了。謹記:想要最佳化 GO 的 if err != nil 還得要考慮整體適合度,不能一廂情願。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.