golang 錯(cuò)誤處理和異常處理

在 Golang 中,錯(cuò)誤處理異常處理是兩個(gè)不同的概念,分別用于處理不同類型的問題。Golang 的設(shè)計(jì)哲學(xué)強(qiáng)調(diào)顯式錯(cuò)誤處理,而異常機(jī)制主要用于不可恢復(fù)的嚴(yán)重問題。以下是它們的詳細(xì)介紹:


1. 錯(cuò)誤處理

在 Golang 中,錯(cuò)誤處理是通過返回值實(shí)現(xiàn)的。函數(shù)通常返回一個(gè) error 類型的值,調(diào)用者需要檢查該值是否為 nil 來判斷是否發(fā)生了錯(cuò)誤。

1.1 基本錯(cuò)誤處理模式

函數(shù)返回 (result, error),調(diào)用者通過檢查 error 來決定如何處理。

示例:

package main

import (
    "errors"
    "fmt"
)

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("division by zero") // 返回錯(cuò)誤
    }
    return a / b, nil // 正常返回結(jié)果
}

func main() {
    result, err := divide(10, 0) // 調(diào)用函數(shù)
    if err != nil {
        fmt.Println("Error:", err) // 錯(cuò)誤處理
    } else {
        fmt.Println("Result:", result)
    }
}

運(yùn)行結(jié)果

Error: division by zero

1.2 自定義錯(cuò)誤

Golang 支持創(chuàng)建自定義錯(cuò)誤類型,通過實(shí)現(xiàn) error 接口的 Error() 方法來自定義錯(cuò)誤信息。

示例:

package main

import "fmt"

// 自定義錯(cuò)誤類型
type MyError struct {
    Code    int
    Message string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}

func doSomething() error {
    return &MyError{Code: 404, Message: "Resource not found"} // 返回自定義錯(cuò)誤
}

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println(err) // 打印自定義錯(cuò)誤
    }
}

運(yùn)行結(jié)果

Error 404: Resource not found

1.3 使用 fmt.Errorf 格式化錯(cuò)誤

Golang 提供了 fmt.Errorf 來生成格式化的錯(cuò)誤信息。

示例:

package main

import (
    "fmt"
)

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("cannot divide %d by zero", a) // 格式化錯(cuò)誤信息
    }
    return a / b, nil
}

func main() {
    _, err := divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
    }
}

運(yùn)行結(jié)果

Error: cannot divide 10 by zero

1.4 errors.Iserrors.As

在 Golang 1.13+ 中,errors 包增加了 errors.Iserrors.As 方法,用于檢查和處理嵌套錯(cuò)誤。

示例:

package main

import (
    "errors"
    "fmt"
)

var ErrNotFound = errors.New("not found")

func findResource(id int) error {
    if id == 0 {
        return fmt.Errorf("resource error: %w", ErrNotFound) // 嵌套錯(cuò)誤
    }
    return nil
}

func main() {
    err := findResource(0)
    if errors.Is(err, ErrNotFound) { // 檢查是否是 ErrNotFound 錯(cuò)誤
        fmt.Println("Resource not found")
    } else {
        fmt.Println("Other error:", err)
    }
}

運(yùn)行結(jié)果

Resource not found

2. 異常處理

Golang 的異常處理是通過 panicrecover 實(shí)現(xiàn)的。它們主要用于處理程序中的不可恢復(fù)錯(cuò)誤,例如邏輯錯(cuò)誤或嚴(yán)重的運(yùn)行時(shí)問題。

2.1 panic

  • panic 會(huì)立即停止當(dāng)前函數(shù)的執(zhí)行,并向調(diào)用棧上傳播,最終導(dǎo)致程序崩潰。
  • 通常用于不可恢復(fù)的錯(cuò)誤,例如數(shù)組越界、空指針訪問等。

示例:

package main

func main() {
    panic("something went wrong") // 觸發(fā) panic
}

運(yùn)行結(jié)果

panic: something went wrong

goroutine 1 [running]:
main.main()
    /path/to/main.go:4 +0x39
exit status 2

2.2 recover

  • recover 用于捕獲 panic,從而恢復(fù)程序的正常運(yùn)行。
  • 必須在 defer 中調(diào)用,否則無法捕獲 panic

示例:

package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r) // 捕獲 panic
        }
    }()

    panic("something went wrong") // 觸發(fā) panic
    fmt.Println("This will not be printed")
}

運(yùn)行結(jié)果

Recovered from panic: something went wrong

2.3 panic 和 recover 的使用場景

  • panic:用于不可恢復(fù)的錯(cuò)誤,例如程序的內(nèi)部邏輯錯(cuò)誤。
  • recover:用于捕獲 panic,從而在某些情況下恢復(fù)程序的運(yùn)行。

示例:在子協(xié)程中捕獲 panic

package main

import (
    "fmt"
    "time"
)

func safeGo(f func()) {
    go func() {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Recovered from panic:", r)
            }
        }()
        f()
    }()
}

func main() {
    safeGo(func() {
        panic("something went wrong in goroutine") // 子協(xié)程觸發(fā) panic
    })

    time.Sleep(1 * time.Second) // 確保主協(xié)程不會(huì)過早退出
    fmt.Println("Main function continues")
}

運(yùn)行結(jié)果

Recovered from panic: something went wrong in goroutine
Main function continues

3. 錯(cuò)誤處理 vs 異常處理

特性 錯(cuò)誤處理 異常處理
機(jī)制 函數(shù)返回值 (error) panicrecover
使用場景 常見的業(yè)務(wù)邏輯錯(cuò)誤 程序中不可恢復(fù)的嚴(yán)重錯(cuò)誤
處理方式 顯式檢查錯(cuò)誤 隱式捕獲(通過 recover
對程序的影響 不影響程序的正常運(yùn)行 未捕獲的 panic 會(huì)導(dǎo)致程序崩潰
推薦使用場景 推薦用于大多數(shù)場景 僅用于異常或不可恢復(fù)的錯(cuò)誤

4. 總結(jié)

  1. 錯(cuò)誤處理是 Golang 的主流方式,通常通過返回 error 值讓調(diào)用者顯式處理。
  2. 異常處理panicrecover)僅用于不可恢復(fù)的錯(cuò)誤,應(yīng)該謹(jǐn)慎使用。
  3. 在 Golang 中,更推薦使用顯式的錯(cuò)誤處理方式,而不是依賴異常機(jī)制。
  4. 對于子協(xié)程中的 panic,可以通過 recover 捕獲,避免影響主程序的運(yùn)行。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容