天天看點

panic defer recover

panic發生時,程式控制權的轉移:

package main

import "fmt"

func main() {
	fmt.Println("Enter function main.")
	caller1()
	fmt.Println("Exit function main.")
}

func caller1() {
	fmt.Println("Enter function caller1.")
	caller2()
	fmt.Println("Exit function caller1.")
}

func caller2() {
	fmt.Println("Enter function caller2.")
	s1 := []int{0, 1, 2, 3, 4}
	e5 := s1[5]
	_ = e5
	fmt.Println("Exit function caller2.")
}
           

輸出:

panic: runtime error: index out of range
Enter function main.

Enter function caller1.
goroutine 1 [running]:
Enter function caller2.
main.caller2()
	E:/GoProgram/awsomeproject/src/go語言核心36講/19錯誤處理/2.go:20 +0x98
main.caller1()
	E:/GoProgram/awsomeproject/src/go語言核心36講/19錯誤處理/2.go:13 +0x6d
main.main()
	E:/GoProgram/awsomeproject/src/go語言核心36講/19錯誤處理/2.go:7 +0x6d
           

Go 語言的内建函數recover專用于恢複 panic,或者說平息運作時恐慌。recover函數無需任何參數,并且會傳回一個空接口類型的值,這裡 的recover需要配合defer使用:

package main

import (
	"fmt"
	"errors"
)

func main() {
	fmt.Println("Enter function main.")
	defer func(){
		fmt.Println("Enter defer function.")
		if p := recover(); p != nil {
			fmt.Printf("panic: %s\n", p)
		}
		fmt.Println("Exit defer function.")
	}()
	// 引發 panic。
	panic(errors.New("something wrong"))
	fmt.Println("Exit function main.")
	
	/**
	輸出:
	Enter function main.
	Enter defer function.
		panic: something wrong
	Exit defer function.
	 */
}
           

如果一個函數中有多條defer語句,那麼那幾個defer函數調用的執行順序是怎樣的?

package main

import "fmt"

func main() {
	defer fmt.Println("first defer")
	for i := 0; i < 3; i++ {
		defer fmt.Printf("defer in for [%d]\n", i)
	}
	defer fmt.Println("last defer")
	/**
	輸出:
		last defer
		defer in for [2]
		defer in for [1]
		defer in for [0]
		first defer

	
	 */
}