面试题答案
一键面试1. recover方法在高并发环境下的挑战
- 捕获特定goroutine的panic:在高并发场景中,每个goroutine都是独立运行的,
recover
只能捕获当前goroutine中的panic。如果一个goroutine发生panic,其他goroutine中的recover
无法捕获该异常,导致难以在统一的地方处理所有goroutine的异常。 - 避免影响其他正常运行的goroutine:当一个goroutine发生panic,如果没有正确处理,可能会导致整个程序崩溃。即使在某个goroutine中使用
recover
捕获了panic,也需要确保不会因为异常处理逻辑而影响到其他正常运行的goroutine。例如,异常处理可能会占用共享资源,从而影响其他goroutine对该资源的访问。
2. 可行的解决方案
可以通过在每个goroutine中使用匿名函数包裹业务逻辑,并在匿名函数中使用 recover
来捕获panic。同时,使用一个 chan
来传递异常信息,以便在主goroutine中统一处理所有goroutine的异常。
3. 代码示例
package main
import (
"fmt"
)
func worker(id int, resultChan chan<- int, errorChan chan<- error) {
defer func() {
if r := recover(); r != nil {
errorChan <- fmt.Errorf("goroutine %d panicked: %v", id, r)
}
}()
// 模拟业务逻辑,这里可能会发生panic
if id == 2 {
panic("simulated panic")
}
result := id * id
resultChan <- result
}
func main() {
numWorkers := 3
resultChan := make(chan int, numWorkers)
errorChan := make(chan error, numWorkers)
for i := 1; i <= numWorkers; i++ {
go worker(i, resultChan, errorChan)
}
go func() {
for i := 0; i < numWorkers; i++ {
select {
case result := <-resultChan:
fmt.Printf("Result from goroutine: %d\n", result)
case err := <-errorChan:
fmt.Printf("Error from goroutine: %v\n", err)
}
}
close(resultChan)
close(errorChan)
}()
select {}
}
在上述代码中:
worker
函数是每个goroutine执行的函数,它使用defer
和recover
来捕获可能发生的panic,并将异常信息通过errorChan
发送出去。- 在
main
函数中,创建了多个worker
goroutine,并通过resultChan
接收正常的计算结果,通过errorChan
接收异常信息。 - 使用
select
语句在主goroutine中统一处理来自不同goroutine的结果和异常,确保在高并发环境下安全、有效地处理异常。