MST

星途 面试题库

面试题:Go中Panic与Recover在并发编程中的深度运用

在Go语言的并发编程环境下,多个goroutine同时运行且可能会触发panic。请设计一个方案,在主goroutine中能够捕获并处理所有子goroutine中触发的panic,同时保证程序在处理完panic后能够继续稳定运行(例如,其他未触发panic的goroutine可以继续工作)。请详细描述实现思路,并给出完整的代码示例,分析该方案在性能和资源管理方面的优缺点。
35.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 使用 sync.WaitGroup 来等待所有子 goroutine 完成。
  2. 在每个子 goroutine 中使用 defer 配合 recover 来捕获 panic
  3. 将捕获到的 panic 信息通过 channel 传递给主 goroutine 进行处理。

代码示例

package main

import (
	"fmt"
	"sync"
)

func worker(id int, wg *sync.WaitGroup, panicCh chan interface{}) {
	defer func() {
		if r := recover(); r != nil {
			panicCh <- fmt.Sprintf("goroutine %d panicked: %v", id, r)
		}
		wg.Done()
	}()
	// 模拟可能触发panic的操作
	if id == 2 {
		panic("simulated panic")
	}
	fmt.Printf("goroutine %d is working\n", id)
}

func main() {
	var wg sync.WaitGroup
	panicCh := make(chan interface{}, 10)

	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go worker(i, &wg, panicCh)
	}

	go func() {
		wg.Wait()
		close(panicCh)
	}()

	for msg := range panicCh {
		fmt.Println("Caught panic:", msg)
	}

	fmt.Println("All goroutines completed, program continues.")
}

优缺点分析

优点

  1. 性能:通过 deferrecover 在子 goroutine 内部捕获 panic,减少了程序崩溃的风险,保证了整体性能不受单个 goroutine 崩溃的影响。
  2. 资源管理:使用 sync.WaitGroupchannel 进行同步和通信,资源管理清晰,每个 goroutine 的生命周期都能得到有效控制。未触发 panicgoroutine 可以继续工作,不会因为其他 goroutine 的问题而被终止,资源得以充分利用。

缺点

  1. 性能deferrecover 本身会带来一定的性能开销,尤其是在大量 goroutine 同时运行且频繁触发 panic 的情况下,这种开销可能会比较明显。
  2. 资源管理:使用 channel 传递 panic 信息,如果 channel 缓冲区设置不合理,可能会导致 goroutine 阻塞,进而影响程序的正常运行。同时,sync.WaitGroupchannel 的使用增加了代码的复杂性,对资源管理和调试带来一定挑战。