Golang錯誤處理函式defer、panic、recover、errors.New介紹

OldBoy~發表於2018-08-30
  1. 在預設情況下,當發生錯誤(panic)後,程式就會終止執行
  2. 如果發生錯誤後,可以捕獲錯誤,並通知管理人員(郵件或者簡訊),程式還可以繼續執行,這當然無可厚非
  3. errors.New("錯誤資訊"),會返回一個error型別的值,表示一個錯誤
  4. panic內建函式,接收一個interface()型別的值(也就是任何值都可以)作為引數,可以接收error型別的變數,輸出錯誤資訊,並退出程式
  5. GO語言追求簡潔優雅,GO語言不類似php支出try catch操作
  6. GO語言中引入的處理方式為:defer、panic、recover
  7. GO可以丟擲一個panic異常。然後在defer中通過recover捕獲異常再處理

自定義錯誤處理運用

package main
import (
    "fmt"
    "errors"
)


//此函式讀取配置檔案資訊
//如果檔名不正確,返回自定義錯誤
func readConfFile(FileName string) (err error) { //返回error型別
    if FileName == "config.ini" {
        return nil //表示沒有錯誤
    } else {
        return errors.New("讀取檔案錯誤")
    }
}

func error_func(){
    err := readConfFile("config.ini")  //這裡故意寫錯,報錯程式碼在第一塊,如果寫對,在第二塊
    if err != nil {
        //如果讀取檔案發生錯誤,就輸出這個錯誤,並終止程式
        panic(err)  //這個函式作用是列印錯誤資訊,並終止程式
    }
    fmt.Println("error_func()繼續執行")
}
func main() {
    error_func()
    fmt.Printf("發生錯誤後面的程式碼")
}



//【報錯資訊】
//一、
// panic: 讀取檔案錯誤

// goroutine 1 [running]:
// main.error_func()
//         D:/goproject/src/main/hello.go:22 +0xdf
// main.main()
//         D:/goproject/src/main/hello.go:27 +0x27
// exit status 2


//二、
// error_func()繼續執行
// 發生錯誤後面的程式碼

recover+defer的運用

package main
import (
    "fmt"
    "time"
)



//這裡舉例,在數學計算中0是不可以作為被除數的
func error_func() {
    //這裡使用defer + recover來捕獲處理異常
    defer func() {  //defer就是把匿名函式壓入到defer棧中,等到執行完畢後或者發生異常後呼叫匿名函式
        err := recover()  //recover是內建函式,可以捕獲到異常
        if err != nil {   //說明有錯誤
            fmt.Println("err=", err)
            //當然這裡可以把錯誤的詳細位置傳送給開發人員
            //send email to admin
        }
    }()
    num1 := 10
    num2 := 0
    res := num1 / num2
    fmt.Println("res=", res)
}

func main() {
    //這樣程式不會輕易掛掉
    error_func()
    i := 0
    for {
        i++
        fmt.Println("發生錯誤後面的程式碼", i)
        time.Sleep(time.Second)
    }

}

defer語句是在return之後執行的,例如:

func test() (result int) {
    defer func() {
        result = 12
    }()
    return 10
}

func main() {
    fmt.Println(test())     // 12
}

在一個函式中panic被呼叫後,其defer語句仍會執行,例如:

package main
import (
    "fmt"
    "errors"
)


func foo()(n int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("再然後④\n")
            n++   
            fmt.Println("最後⑤\n")
        }
    }()
    fmt.Println("首先①\n")
    n++       
    fmt.Printf("然後②n=%v\n" ,n) 
    fmt.Println("然後③\n")     
    panic(errors.New("i'm a bug"))  
    fmt.Println("沒走\n")
            
    return n
}
func main() {
    n := foo()
    fmt.Printf("n最後的值%v", n)
}
首先①
然後②n=1
然後③
再然後④
最後⑤
n最後的值2

 

相關文章