3 回答

TA貢獻1829條經驗 獲得超13個贊
錯誤很復雜,因為,嗯,錯誤只是很復雜。
Dave Cheney 的博客文章包括以下聲明:
我得出的結論是,沒有單一的方法可以處理錯誤。
我完全同意??紤]一些簡單的事情,比如“從文件中讀取數據”。這可能會失敗。但是為什么它會失敗,你能對這些失敗做些什么嗎?
以下是它可能失敗的一些原因。這并不意味著是所有可能原因的完整列表,只是其中一些原因:
也許該文件不存在。它應該,但只是沒有。
您可能對此無能為力。
也許該文件確實存在,但您沒有訪問它的權限。你應該,但你只是不這樣做。
除非您具有管理員訪問權限,否則您可能對此無能為力,在這種情況下,您可以授予自己權限并繼續。
也許該文件存在并且您有權訪問它,但數據已損壞。
對此您可能無能為力,但如果系統是自我修復的(此類系統存在),這可能是暫時的。
也許該文件暫時無法訪問,因為它位于網絡上并且網絡已分區。
這類似于案例 3:等待和重試可能會解決問題(實際上它可能比案例 3 更有可能)。
... [他建議] 包裝自定義錯誤類型并在自定義接口上使用類型斷言。我發現這很冗長,需要大量額外的代碼。
確實如此。它還需要首先產生錯誤的人的合作,以便您可以做出這些細微的區分。那是因為您正在處理真正復雜的硬件和軟件系統。
這不是很令人滿意,但這是真的。幸運的是,對于很多軟件來說,很多錯誤情況都可以歸結為“不是我的問題”:上面的前兩個示例無法打開和讀取某些文件(不存在或權限被拒絕)可以放入這個組。如果您正在編寫文件列表實用程序或類似的東西,這可能沒問題。如果您正在編寫代碼來運行起搏器,則停止并顯示錯誤消息(“致命:無法報告心率”)很可能是,呃,致命的。你需要考慮上下文。

TA貢獻2039條經驗 獲得超8個贊
如果你用 包裝一個錯誤err
,fmt.Errorf
你可以檢查錯誤errors.Is
例子:
var ExpectedError = errors.New("This is an error") err := fmt.Errorf("I am now wrapping %w ",ExpectedError) fmt.Println("Checking error", errors.Is(err, ExpectedError))
https://play.golang.org/p/wtOeopA-f5B

TA貢獻1862條經驗 獲得超6個贊
錯誤為不應運行的代碼提供了保護,并提供了處理故障后狀態的方法。
Swift 和 Rust 的學習應用在慣用的 go 風格中:
在應用程序級別,我希望將所有錯誤集中在一個地方,以便我知道該應用程序處理哪些錯誤。
所有關于錯誤的單元測試和應用程序行為都將基于我的應用程序定義的錯誤類型和錯誤變量。為此,我必須編寫從 lib 錯誤到 AppErrors 的轉換,并在應用程序首次檢查錯誤的任何地方使用它們。
因此,如果任何庫更改或被等效庫替換,則只需更改錯誤的轉換(適應)。應用程序錯誤處理策略的其余部分保持原樣并經過測試。
錯誤類型實現接口或者我們只是使用錯誤類型檢查/切換是次要的。
這是該方法的示例。我更喜歡使用 const 來最小化強制轉換。我相信這會更快、更易讀。
package main
import (
"fmt"
"os"
)
type ErrorType int
const (
ReaderEndError ErrorType = iota + 1
ResourceNotFoundError
)
type AppError struct {
ErrType ErrorType
s string
error
}
func (ae AppError) Error() string {
return ae.s
}
func (ae *AppError) GetType() ErrorType {
return ae.ErrType
}
func main() {
_, err := readData("notexists")
if err != nil {
if ae, ok := err.(AppError); ok {
//should use switch case in actual startegy
if ae.ErrType == ResourceNotFoundError {
if ae.error != nil {
fmt.Println("Inner wrapped details (use for logging)", ae.error)
}
fmt.Println("handle ResourceNotFoundError here")
}
}
}
}
//sample func
func readData(file string) (*string, error) {
_, err := os.Open(file)
if err != nil {
//switch case here actually
e, _ := err.(*os.PathError)
//actually should have many helper conversion functions to do below conversions
return nil, AppError{ResourceNotFoundError, "Not found", e}
}
//assume read data
data := string("data")
return &data, nil
}
- 3 回答
- 0 關注
- 256 瀏覽
添加回答
舉報