2016-08-24 133 views
2

因此,大多數go錯誤處理的示例只是將任何錯誤都傳遞迴堆棧。在某些時候,這些需要解釋,而這正是我想要做的。 這是我嘗試的一個片段:解釋Golang錯誤代碼

resp, err := http.Get(string(url)) 
    defer out_count.Dec() 

    if err != nil { 

      switch err { 
      case http.ErrBodyReadAfterClose: 
        fmt.Println("Read after close error") 
      case http.ErrMissingFile: 
        fmt.Println("Missing File") 
      {some more cases here} 
      case io.EOF: 
        fmt.Println("EOF error found") 
      default: 
        fmt.Printf("Error type is %T\n", err) 
        panic(err) 
      } 
      return 

這不是工作,雖然我目前的情況下(編輯刪除URL}:

ERROR: Failed to crawl "http://{removed URL}" 
Error type is *url.Error 
panic: Get http://{removed url}: EOF 

goroutine 658 [running]: 
runtime.panic(0x201868, 0x106352c0) 
     /usr/lib/go/src/pkg/runtime/panic.c:279 +0x1a0 
github.com/cbehopkins/grab/grab.crawl(0x10606210, 0x27, 0x105184b0, 0x105184e0, 0x10500460) 

我不能想出一個辦法來獲得switch語句來捕獲這個錯誤,因爲錯誤的文本每次都會改變,並且沒有明確的值,我可以捕捉到(因爲URL一直在改變)。現在,也許我可以在case語句中做某種正則表達式匹配,或者對錯誤字符串進行分片,但是感覺這是一種解決此問題的非常糟糕的方式。

有什麼建議嗎?必須有一種慣用的方式來肯定地發現這樣的錯誤?

回答

3

最簡單的方法是在你的代碼包級別的錯誤值:

var URLFetchError = errors.New("Cannot fetch URL") 

url := "http://www.google.com" 
res, err := http.Get(url) 
if err != nil { 
    return URLFetchError 
} 

switch就變成了:

switch err { 
case http.ErrBodyReadAfterClose: 
    fmt.Println("Read after close error") 
case URLFetchError: 
    fmt.Println("Error fetching URL") 

如果你想通過與更多的信息錯誤,您可以創建自己的自定義錯誤:

type MyError struct { 
    URL string 
} 

func (e MyError) Error() string { 
    return fmt.Sprintf("Error getting: %v", e.URL) 
} 

然後,您可以根據需要創建此錯誤。例如:

url := "http://www.google.com" 
res, err := http.Get(url) 
if err != nil { 
    return MyError{url} 
} 

最後,在你的錯誤檢查方法,你可以使用類型轉換,而不是簡單的開關以獲取錯誤:

switch err.(type) { 
case MyError: 
    fmt.Println("Error:", err) 
default: 
    fmt.Println("No Error") 
} 

在你的情況,因爲你有定期的混合錯誤,您可以包括此檢查嵌套switch

switch err { 
case http.ErrBodyReadAfterClose: 
    fmt.Println("Read after close error") 
case http.ErrMissingFile: 
    fmt.Println("Missing File") 
case io.EOF: 
    fmt.Println("EOF error found") 
default: // check for custom errors 
    switch err.(type) { 
    case MyError: 
     fmt.Println("custom error:", err) 
    default: 
     panic(err) 
    } 
} 
+0

感謝您的詳盡答案! 我認爲這個問題是我得到frm標準html包的錯誤沒有提供我可以匹配的這些錯誤定義。 但是你是正確的,我可以先對錯誤類型進行切換,然後再對錯誤細節進行切換。 對於這個應用程序來說,這就足夠了,現在我只需要弄清楚如何將這個請求反饋回標準的html包。 謝謝 –

1

您可以實現錯誤界面並創建您自己可能更容易處理的錯誤。

對於運行時錯誤a.k.a恐慌。你可以通過在你認爲可能恐慌的函數中包含recover()來恢復。它在panicing函數返回之前調用。

defer func() { 
    if r := recover(); r != nil { 
     if _, ok := r.(runtime.Error); ok { 
       err = r.(error) //panic(r) 
      } 
      err = r.(error) 
     } 
    }() 
} 
+0

啊,我覺得你有誤解,恐慌是有我停止代碼時,有我的代碼無法處理錯誤。它給我提供了一個調試,說我沒有抓住所有我應該遇到的問題。 儘管感謝 –

+0

也許你不明白「實現錯誤界面」的含義是因爲這就是你選擇的答案。 – Sridhar