wordpress 文章推薦一篇福建優(yōu)化seo
自定義錯誤
?Go語言中? 錯誤使用內建的 error 類型表示, error類型是一個接口類型:定義如下:
?error 有一個 Error() 的方法‘所有實現(xiàn)該接口的類型 都可以當做一個錯誤的類型;Error()方法輸入具體錯誤描述,在打印錯誤時 可以調用 Error() 來輸出錯誤
type error struct {Error() string }
對于簡單的數(shù)據(jù)類型,一個 println 就可以了,
但是對于復雜類型 我們可以通過繼承接口的方式 靈活的方式進行:
例如一個計算面積的函數(shù):需要判斷輸入是否合法:比如輸入負數(shù)則報錯!
??
?方式1:
//計算面積 //輸入兩個數(shù) 返回 面積和錯誤 func area(a, b int) (int, error) {if a < 0 || b < 0 {//第一種//return 0, errors.New("計算長度 不能為負數(shù)")//第二種return 0, fmt.Errorf("計算長度 不能為負數(shù); 長度%d,寬度%d 不能小于0", a, b)//return 0, &areaError{"計算長度 不能為負數(shù)", a, b}}return a * b, nil }//調用:a := 20 b := -56r, err := area(a, b) if err != nil {fmt.Println(err)return } fmt.Println("area:", r)輸入: 計算長度 不能為負數(shù)計算長度 不能為負數(shù); 長度20,寬度-56 不能小于0
??
?方式2:
//定義錯誤結構體 type areaError struct {err string //錯誤描述length int //寬度width int //長度 } //實現(xiàn)一個接口 func (e *areaError) Error() string {//return fmt.Sprintf("length %d, width %d", e.length, e.width)return e.err }//求面積函數(shù) func area(a, b int) (int, error) {if a < 0 || b < 0 {return 0, &areaError{"計算長度 不能為負數(shù)", a, b}}return a * b, nil }//調用: a := 20 b := -56r, err := area(a, b) //寫法1 if err != nil {if err, ok := err.(*areaError); ok {fmt.Printf("length %d or width %d is less than zero\n", err.length, err.width)fmt.Println(err)return}fmt.Println(err)return } fmt.Println("area:", r)輸出: length 20 or width -56 is less than zero 計算長度 不能為負數(shù)
?方式3:
//定義結構體和 函數(shù) type areaError struct {err string //錯誤描述length int //寬度width int //長度 }func (e *areaError) Error() string {//return fmt.Sprintf("length %d, width %d", e.length, e.width)return e.err }func (e *areaError) widthNegative() bool {return e.width < 0 }func (e *areaError) lengthNegative() bool {return e.length < 0 }//面積函數(shù)的定義 func area(length, width int) (int, error) {err := ""if length < 0 {err += "length is negative"}if width < 0 {err += "width is negative"}if err != "" {return 0, &areaError{err: err, length: length, width: width}}return length * width, nil }//調用: a := 20 b := -56r, err := area(a, b) if err != nil {if err, ok := err.(*areaError); ok {if err.lengthNegative() {fmt.Println("Length is error :", err.length)}if err.widthNegative() {fmt.Println("width is error :", err.width)}fmt.Printf("length:%d, width:%d\n", err.length, err.width)return}fmt.Println(err) } fmt.Println("area:", r)//輸出: width is error : -56 length:20, width:-56
異常
異常和錯誤 是兩個不同的概念,容易混淆:
- 錯誤是指:在有可能出現(xiàn)問題的地方,出現(xiàn)了問題
- 異常是指:在不應該出現(xiàn)問題的地方,出現(xiàn)了問題
?
go 中的處理異常的主要有兩種:
panic :會導致程序會終止,在編寫程序的時候 盡量使用錯誤; 只有在程序不能繼續(xù)進行下去的時候在使用? panic,在發(fā)生 panic 的時候使用 recover 防止程序終止
// 會導致程序會終止,在編寫程序的時候 盡量使用 錯誤; 只有在程序不能繼續(xù)進行下去的時候在使用: panic, recover func myTest() {defer fmt.Println("myTest defer")panic("myTest panic") }func main() {defer fmt.Println("main defer")myTest()fmt.Println("main ...") }輸出:帶錯誤碼的異常中斷,并且程序沒有執(zhí)行完整; 沒有打印 fmt.Println("main ...")myTest defer main defer panic: myTest panicgoroutine 1 [running]: main.myTest()D:/awesomeProject/grammar/chapter08/main.go:18 +0x73 main.main()D:/awesomeProject/grammar/chapter08/main.go:7 +0x70Process finished with the exit code 2
recover :recover 類似與其他語音 try catch, 但是它只有在 相同的協(xié)程中才能 recover到異常,繼續(xù)執(zhí)行代碼 不至于奔潰
// 在發(fā)生 panic 的時候, recover 防止程序終止 // recover 類似與 try catch 只有在相同的協(xié)程中才能 recover到異常,繼續(xù)執(zhí)行代碼 不至于奔潰 func outOfArray(x int) {defer func() {if err := recover(); err != nil {fmt.Println(err)}}()var array [5]intarray[x] = 1 }func main() {outOfArray(6)fmt.Println("main ...")}輸出: 帶錯誤輸出,并且程序繼續(xù)往下執(zhí)行 (執(zhí)行完整) 輸出 fmt.Println("main ...")runtime error: index out of range [6] with length 5 main ...Process finished with the exit code 0