1. 程式人生 > >defer panic recover

defer panic recover

defer

1.詞義

    defer推遲  recover恢復  panic恐慌

2.panic

   panic 型別interface{}型別

   panic恐慌 不會再往下執行了

3.recover

    panic 之後不會立刻返回  會傳遞至defer  defer裡面有recover的話  會進行捕獲panic的內容

4.defer

    defer推遲 可以多次推遲  棧的資料結構

5.正常情況

package main

import (
	"fmt"
)

func main() {
  test()
}
 
func minicError(key string) error {
  return fmt.Errorf("mimic error: %s", key)
}
 
func test() {
	fmt.Println("start test")
	
	err := minicError("1")
	
	defer func() {
		fmt.Println("start defer")
		
		if err != nil {
			fmt.Println("defer error:", err)
		}
	}()
	
	fmt.Println("end test")
}

--------------------------------------

start test
end test
start defer
defer error: mimic error: 

6.defer與return

return是在defer之後執行的

7.recover與panic

無值時候:Recover方法被呼叫,但是沒有任何的panic發生,recover方法只會返回nil;

有值時候:如果有panic發生,那麼panic就停止  並且把panic的賦值傳遞給recover。

總結:如果有了panic 那麼後面的都不執行了  但是會把值傳遞給recover  recover會捕獲panic的值   並且程式不會崩潰

7.例子

這個例子說明了recover進行捕獲panic的內容

package main

import "fmt"
import "math"

func foo(a int) {
	defer fmt.Println("foo退出來了")
	defer func() {

		if r := recover(); r != nil {
			fmt.Printf("捕獲到的錯誤:%s\n", r)
		}
	}()
	if a < 0 {
		panic("必須輸入大於0的數")
	}
	fmt.Println("該數的方根為:", math.Sqrt(float64(a)))
}

func main() {
	var a int
	a = 10
	fmt.Printf("a=%d\n", a)
	foo(a)
	var b int
	b = -10
	fmt.Printf("b=%d\n", b)
	foo(b)
	fmt.Println("該goroutine還可以執行")
}
// a=10
// 該數的方根為: 3.1622776601683795
// foo退出來了
// b=-10
// 捕獲到的錯誤:必須輸入大於0的數
// foo退出來了
// 該goroutine還可以執行