Sentinel Errors(哨兵錯誤)
Error Types(自定義錯誤型別)
Opaque Errors(非透明錯誤)
1.Sentinel errors(哨兵錯誤)
計算機程式設計中使用一個特定的值來表示不可能進一步處理的做法叫
Sentinel Error
(哨兵錯誤)
。如C語言中我們常常返回一個整數值表示成功還是失敗。
透過下面程式碼我們得出結論,如果使用 Sentinel Error 我們會向下面這樣判斷,導致寫死在程式碼中,如果這時候方法的作者覺得錯誤值不合理,把錯誤值改了。導致呼叫者也會更改。所以我們永遠不應該使用檢測error。Error的輸出
err := saveUser()switch err { case “User Not Found In Database”: fmt。Println(“User Not Found”) case “Save User to Database Fail”: fmt。Println(“User Not Found”) default: fmt。Println(err。Error())}
Sentinel Error用法:使用errors。New建立錯誤,並賦值給Err字首的變數。
io包中的示例:var EOF = errors。New(“EOF”)
var ErrUserNotFound = errors。New(“User Not Found In Database”)var ErrSaveUserFail = errors。New(“Save User to Database Fail”)err := saveUser()switch err { case ErrUserNotFound: fmt。Println(“User Not Found In Database”) case ErrSaveUserFail: fmt。Println(“Save User to Database Fail”) default: fmt。Println(err。Error())}
使用Sentinel Error最不靈活,呼叫者只能做等值判斷,有時候我們只有錯誤值,沒法判斷具體的錯誤在哪兒,這個時候Sentinel Error 沒辦法為我們需要更多的上下文。
結論我們應該儘可能避免 Sentinel Error
。
Sentinel Error的特點:
1。 只能做等值判斷
2。 無法做斷言
3。 無法提供更多的上下文資訊
4。 建立包與包之間的依賴
5。 成為公共API的一部分,增加了包的表面積
5。1。 如果API的公共函式或者方法返回特定錯誤
5。2。 如果API的介面返回了 Sentinel Error 錯誤,該介面的實現也被限制返回Sentinel Error 錯誤。
Sentinel Error應用場景:
1。 應用不會有第三方匯入包,這個時候我們可以使用 Sentinel Error2。 如果API只有一種錯誤,也不需要攜帶上下文,不需要斷言我們可以使用 Sentinel Error
2.Error Types(自定義錯誤型別)
Error type 就是實現了 error 介面的自定義型別。
有時候我們想要攜帶更多的上下文資訊,使用Sentinel Error無法做到。結論雖然 Error Type比 Sentinel Error攜帶了更多得錯誤資訊,但是 Error Type 和 Sentinel Error有相同的問題。如果實在無法避免,至少應該避免公開Error Type。
以下是參考網上文章的程式碼,也可以去看 fs。PathError和 os。SyscallError。
type MyError struct { Msg string File string Line int}func (e *MyError) Error() string { return fmt。Sprintf(“%s:%d: %s”, e。File, e。Line, e。Msg)} err := something()switch err := err。(type) { case nil: // call succeeded, nothing to do case *MyError: fmt。Println(“error occurred on line:”, err。Line) default: // unknown error}
os。SyscallError
fs。PathError
Error Type的特點
1。 可以攜帶更多的上下文資訊
2。 可以使用斷言或者型別切換,但是必須公開 Error Type
3。 Error Type 和 Sentinel Error有相同的問題
4。 實在無法避免,至少應該避免公開Error Type
3. Opaque Errors(非透明錯誤)
呼叫者知道發生了錯誤,但是無法看到錯誤的內部。呼叫者只知道關於操作的結果是成功還是失敗。我們稱為
Opaque Error(非透明錯誤)
為了讓程式碼和呼叫之間的依賴最少,使用簡單。
type temporary interface { Temporary() bool}// 如果 err 是臨時的,IsTemporary 返回 true。func IsTemporary(err error) bool { te, ok := err。(temporary) return ok && te。Temporary()}
Opaque Error的特點
1。程式碼和呼叫之間的依賴最少
2。使用簡單開箱即用
3。判斷行為,而不是型別
4。只有斷言行為的方法,才會成為公共API
1。在日常開發中我們建議使用Opaque Errors(非透明錯誤)
2。如io包中的io。EOF,適用IsEOF()方法判斷就比使用 Sentinel Error更好
參考文章:Don’t just check errors, handle them gracefully「連結」
對Go語言的錯誤使用套路,你有其他建議或者不同的意見歡迎下方留言