閱讀1017 返回首頁    go 阿裏雲 go 技術社區[雲棲]


為什麼我不會舍棄Python投奔Go語言

最近,由於一篇“為什麼我不會舍棄Python投奔Go語言(英文)”的博客,我收到了大量的郵件,這篇文章中,作者說Go語言除了“用返回值來處理異常錯誤”這點外,其它的都非常好。我想寫出一點東西,解釋一下Go語言為什麼這樣做,這會對大家都有用。


本文作者:Russ Cox

在Go語言中,規定的方式是,函數返回錯誤信息。這沒什麼。如果一個文件並不存在,op.Open函數會返回一個錯誤信息。這沒什麼。如果你向你一個中斷了的網絡連接裏寫數據,net.Conn裏的Write方法會返回一個錯誤。這沒什麼。這種狀況在這種程序中是可以預料到的。這種操作就是容易失敗,你知道程序會如何運行,因為API的設計者通過內置了一種錯誤情況的結果而讓這一切顯得很清楚。

從另一方麵講,有些操作基本上不會出錯,所處的環境根本不可能給你提示錯誤信息,不可能控製錯誤。這才是讓人痛苦的地方。典型的例子;一個程序執行 x[j],j值超出數組邊界,這才痛苦。像這樣預料之外的麻煩在程序中是一個嚴重的bug,一般會弄死程序的運行。不幸的是,由於這種情況的存在,我們很難寫出健壯的,具有自我防禦的服務器——例如,可以應付偶然出現的有bug的HTTP請求處理器時,不影響其他服務的啟動和運行。為解決這個問題,我們引入了恢複機製,它能讓一個go例程從錯誤中恢複,服務餘下設定的調用。然而,代價是,至少會丟失一個調用。這是特意而為之的。引用郵件中的原話:“這種設計不同於常見的異常控製結構,這是一個認真思考後的決定。我們不希望像java語言裏那樣把錯誤和異常混為一談。”

我剛開始提到的那篇文章裏問“為什麼數組越界造成的麻煩會比錯誤的網址或斷掉的網絡引出的問題要大?”答案是,我們沒有一種內聯並行的方法來報告在執行x[j]期間產生的錯誤,但我們有內聯並行的方法報告由錯誤網址或網絡問題造成的錯誤。

使用Go語言中的錯誤返回模式的規則很簡單:如果你的函數在某種情況下很容易出錯,那它就應該返回錯誤。當我調用其它的程序庫時,如果它是這樣寫的,那我不必擔心那些錯誤的產生,除非有真正異常的狀況,我根本沒有想到需要處理它們。

有一個你需要記在心裏的事情是,Go語言是為大型軟件設計的。我們都喜歡程序簡潔清晰,但對於一個由很多程序員一起開發的大型軟件,維護成本的增加很難讓程序簡潔。異常捕捉模式的錯誤處理方式的一個很有吸引力的特點是,它非常適合小程序。但對於大型程序庫,如果對於一些普通操作,你都需要考慮每行代碼是否會拋出異常、是否有必要捕捉處理,這對於開發效率和程序員的時間來說都是非常嚴重的拖累。我自己做開發大型Python軟件時感受到了這個問題。 Go語言的返回錯誤方式,不可否認,對於調用者不是很方便,但這樣做會讓程序中可能會出錯的地方顯的很明顯。對於小程序來說,你可能隻想打印出錯誤,退出程序。對於一些很精密的程序,根據異常的不同,來源的不同,程序會做出不同的反應,這很常見,這種情況中,try + catch的方式相對於錯誤返回模式顯得冗長。當然,Python裏的一個10行的代碼放到Go語言裏很可能會更冗長。畢竟,Go語言主要不是針對10行規模的程序的。

就是要說明這一點:Go語言程序員認為,把error作為一種內置的類型是非常重要的。

附言

有時,你會發現,一種非本地的goto語句被當作錯誤恢複的方法,就像C語言裏的longjmp 和 setjmp。這也不錯,但最好隻在內部用。如果調用者需要知道錯誤恢複的走向,那你的這種方式就不好了。

最後更新:2017-04-03 22:30:57

  上一篇:go POJ 3304 判斷直線與線段相交
  下一篇:go Python開發者應該知道的7個開發庫