Goroutine 嚴重故障處理

程序中啓用多個Goroutine,如果其中一個Goroutine因爲一些隱式的運行時錯誤將調用panic,如果沒有合適的處理,將導致所有的Goroutine終止。

嚴重故障 panic

  • Go語言提供了一個內置的panic方法,用來創建一個運行時錯誤並結束當前程序。
  • 它將立刻中斷當前函數的執行,並展開當前Goroutine的調用棧,依次執行之前註冊的defer函數。當棧展開操作達到該Goroutine棧頂端時,程序將終止。
  • 對於一些隱式的運行時錯誤,如切片索引越界、類型斷言錯誤等情形下,panic方法就會被調用。)

恢復 revocer

  • 對於panic,可以使用Go的內建recover方法重新獲得Goroutine的控制權,並將程序恢復到正常執行的狀態。
  • 調用recover方法會終止棧展開操作並返回之前傳遞給panic方法的那個參數。由於在棧展開過程中,只有defer函數會被執行,因此recover的調用必須置於defer函數內纔有效。

Goroutine中panic導致整個程序終止

當在一個Goroutine中發生panic調用時會終止整個程序,如下,創建多個Goroutine,由於panic導致整個程序崩潰,其它Goroutine沒有執行

package main

import (
   "fmt"
)

func test(n int, c chan int) {
   defer func() {
   	fmt.Printf("test: %d\n", n)
   	c <- n
   }()

   panic(fmt.Sprintf("panic: %d", n))
}

func main() {
   c := make(chan int, 0)

   for i := 0; i < 10; i++ {
   	go test(i, c)
   }

   for i := 0; i < 10; i++ {
   	<-c
   }
}

打印報錯:

	test: 9
	test: 1
	panic: panic: 9
	
	goroutine 14 [running]:
	main.test(0x9, 0xc000062060)
		/Users/chicheng/go/src/work/main.go:16 +0x106
	created by main.main
		/Users/chicheng/go/src/work/main.go:23 +0x6f
	exit status 2

Goroutine中recover恢復正常執行

recover在panic執行後會獲得Goroutine控制權,其它Goroutine可以繼續執行

package main

import (
	"fmt"
)

func test(n int, c chan int) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
		c <- n
	}()

	panic(fmt.Sprintf("panic: %d", n))
}

func main() {
	c := make(chan int, 0)

	for i := 0; i < 10; i++ {
		go test(i, c)
	}

	for i := 0; i < 10; i++ {
		<-c
	}
}

打印結果:

	panic: 9
	panic: 3
	panic: 1
	panic: 0
	panic: 4
	panic: 6
	panic: 7
	panic: 2
	panic: 8
	panic: 5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章