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

你可能感兴趣的:(golang)