最近社羣的同學和 Go 官方又因為錯誤處理的提案屢屢被否,發生了一些小的摩擦。也非常難得的看到核心團隊成員首次表達了目前的態度和情況。
基於此,我們今天進行該內容分享。緊跟 Go 官方最新進展。
快速背景
Go 的錯誤處理機制,主要是依賴於 if err != nil
的方式。因此在對函式做一定的封裝後。
程式碼會呈現出以下樣子:
jy1, err := Foo1() if err != nil { return err } jy2, err := Foo2() if err != nil { return err } err := Foo3() if err != nil { return err } ...
有部分開發者會認為這比較的醜陋、混亂且難以閱讀。因此 Go 錯誤處理的最佳化,也是社羣裡一直反覆提及和提出的領域。飽受各類爭議。
新提案:追求類似 try-catch
最近一位國內的同學 @xiaokentrl 提了個類似 try catch error 的新提案,試圖用魔法打敗魔法。
原作者給出的提案內容是:
1、新增環境變數做開關:
ERROR_SINGLE = TRUE //error_single = true
2、使用特定識別符號來做 try-catch:
Demo1 單行錯誤處理:
//Single-line error handling file, err := os.Create("abc.txt") @ return nil , err defer file.Close()
Demo2 多行錯誤處理:
func main() { //Multiline error handling :@ file, err:= os.Open("abc.txt") defer file.Close() buf := make([]byte, 1024) _, err2 := file.Read(buf) @ err | err2 return ... }
主要的變化內容是:利用標籤 @ 新增一個類似 try-catch 的程式碼區塊,並新增運算子和相關錯誤處理的聯動規則。
這個提案本身,其實就是以往講到的 goto error 和 check/with 這種類似 try-catch 的模式。
當然非常快的就遭到了 Go 核心團隊的反對:
@Ian Lance Taylor 表示:由於很難處理宣告和應用,如果一個標籤的作用域中還有其他變數,就不能使用 goto。
新的爭端:官方你行你上
社羣中有同學看到這一次次被否的錯誤處理和關聯提案們,深感無奈和無語。他發出了以下的質疑:
“為什麼不讓 Ian Lance Taylor 和/或 Go 核心團隊的其他成員提出改進的錯誤處理框架的初始原型,然後讓 Go 社羣參與進來,為其最終形式做出貢獻呢?Go 中的泛型正是這樣發展到現在的。
如果我們等待 Go 社羣提出最初的原型,我認為我們將永遠不會有改進的 Go 錯誤處理框架,至少在未來幾年內不會。”
但其實很可惜,因為人家真幹過。
Go 核心團隊是有主動提出過錯誤處理的最佳化提案的,提案名為《Proposal: A built-in Go error check function, try》,快速講一下。
以前的程式碼:
f, err := os.Open(filename) if err != nil { return …, err // zero values for other results, if any }
應用該提案後的新程式碼:
f := try(os.Open(filename))
try 只能在本身返回錯誤結果的函式中使用,且該結果必須是外層函式的最後一個結果引數。
不過很遺憾,該官方提案,喜提有史以來被否決最多的提案 TOP1:
最終該提案也由於形形色色的意見,最終涼了。感覺也給 Go 核心團隊潑了一盆涼水,因為這是繼 check/handle 後的 try,到目前也沒有新的官方提案了。
Go 官方迴應
本次提及的新提案下,大家的交流愈演愈烈,有種認為就是 Go 核心團隊故意不讓錯誤處理得到更好的改善。
此時 Go 核心團隊的元老之一 @Ian Lance Taylor 站出來發聲,詮釋了目前 Go 團隊對此的態度。這也是首次。
具體內容如下:
“我們願意考慮一個有良好社羣支援的好的錯誤處理提案。
不幸的是,我很遺憾地說,基本上所有新的錯誤處理提案都不好,也沒有社羣支援。例如,這個提案有 10 個反對票,沒有贊成票。我當然會鼓勵人們在廣泛使用這門語言之前,避擴音交錯誤處理提案。
我還鼓勵人們審查早期的提案。它們在這裏:github.com/golang/go/i… 。目前已有 183 個並在不斷增加。
我自己閱讀了每一個。重要的是,請記住,對已被否決提案的微調的新提案也幾乎肯定也會被否決。
並且請記住,我們只會接受一個與現有語言契合良好的提案。例如:這個提案中使用了一個神奇的 @ 符號,這完全不像現有語言中的任何其他東西。
Go 團隊可能會在適當的時候提出一個新的錯誤處理提案。然而,正如其他人所說,我們最好的想法被社羣認為是不可接受的。而且有大量的 Go 程式設計師對現狀表示滿意。”
總結
目前 Go 錯誤處理的情況和困境是比較明確的,很多社羣同學會基於以往已經被否決的舊提案上進行不斷的微改,再不斷提交。
現階段都是被全面否定的,因為即使做了微調,也無法改變提案本身的核心思想。
而 Go 官方自己提出的 check/handle 和 try 提案,在社羣中也被廣大的網友否決了。還獲得了史上最多人否決的提案的位置。
現階段來看,未來 1-3 年內在錯誤處理的最佳化上仍然會繼續僵持。