Go 語言錯誤處理機制
錯誤型別
Go 的內建錯誤型別透過 error
介面提供了一種簡單而有效的錯誤處理機制。
error 介面
在 Go 中,error
是一個內建介面,定義如下:
type error interface {
Error() string
}
error
介面只有一個方法 Error()
,返回一個描述錯誤的字串。這使得任何實現了 Error()
方法的型別都可以被視為錯誤。
建立自定義錯誤
開發者可以透過實現 error
介面來自定義錯誤型別。例如:
type MyError struct {
Message string
Code int
}
func (e *MyError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}
在這個例子中,MyError
是一個自定義錯誤型別,包含錯誤訊息和錯誤程式碼。實現 Error()
方法後,MyError
型別可以作為錯誤使用。
使用內建錯誤型別
Go 標準庫提供了一些內建的錯誤型別,例如:
fmt.Errorf
用於建立帶有格式化字串的錯誤。
err := fmt.Errorf("failed to open file: %s", filename)
errors.New
用於建立一個簡單的錯誤。
err := errors.New("an error occurred")
錯誤包裝
從 Go 1.13 開始,可以使用 fmt.Errorf
來包裝錯誤,以便提供更多上下文資訊。透過 %w
語法,可以將原始錯誤作為新錯誤的一部分:
originalErr := errors.New("original error")
wrappedErr := fmt.Errorf("an additional context: %w", originalErr)
檢查錯誤型別
可以使用 errors.Is
和 errors.As
來檢查錯誤的型別,方便處理不同型別的錯誤:
if errors.Is(err, specificErr) {
// 處理特定型別的錯誤
}
返回錯誤
返回錯誤的基本用法如下:
func doSomething() error {
// 發生錯誤時返回
return fmt.Errorf("an error occurred")
}
檢查錯誤
檢查返回錯誤的基本示例:
if err := doSomething(); err != nil {
fmt.Println("Error:", err)
}
panic 與 recover
panic()
是 Go 語言中的一個內建函式,用於觸發恐慌狀態。它主要用於處理程式中不可恢復的錯誤,導致程式停止執行並開始回溯。
當 panic()
被呼叫時,Go 會執行以下步驟:
- 停止當前函式的執行:當前函式會立即停止執行,所有未完成的操作(如
defer
語句)會被執行。 - 逐層回溯:程式會逐層回溯,執行每層呼叫棧中的
defer
語句,直到找到一個可以捕獲panic
的recover()
。 - 程式崩潰:如果沒有任何
recover()
捕獲這個panic
,程式將列印錯誤資訊並退出。
recover()
是 Go 語言中用於處理恐慌狀態的內建函式。它的主要作用是捕獲因 panic
觸發的異常,以便程式能夠繼續執行,而不是完全崩潰。
recover()
只能在 defer
宣告的函式中使用。它的功能是捕獲 panic
產生的值,返回該值,如果沒有發生 panic
,則返回 nil
。
示例
package main
import (
"fmt"
)
func mayPanic() {
panic("something went wrong!")
}
func safeFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
mayPanic() // 觸發 panic
fmt.Println("This will not be printed")
}
func main() {
safeFunction()
fmt.Println("Program continues after recovery.")
}
輸出結果:
Recovered from panic: something went wrong!
Program continues after recovery.
在上面的示例中,mayPanic
函式觸發了一個 panic
,但透過 recover()
捕獲並處理了這個 panic
,程式得以繼續執行。
設計模式:返回錯誤 vs使用 panic
-
返回錯誤:這種模式適合於可以預期的錯誤,如檔案未找到、網路請求失敗等。呼叫者可以透過檢查錯誤值來決定下一步的處理邏輯。
func readFile(filename string) error { // 模擬讀取檔案錯誤 return fmt.Errorf("file not found: %s", filename) }
-
使用
panic
:適合處理嚴重的程式錯誤,例如邏輯錯誤、配置錯誤等。這類錯誤通常表明程式碼中存在缺陷,無法繼續執行。func main() { if err := performCriticalOperation(); err != nil { panic(err) // 不可恢復的錯誤 } }