MST

星途 面试题库

面试题:如何设计一个并发安全的Go程序,使其在panic发生后能有效恢复且不影响其他正常运行的goroutine?

假设你正在开发一个高并发的Go应用,该应用涉及多个goroutine同时处理不同任务。要求设计一种方案,确保当某个goroutine发生panic时,能进行有效恢复,同时不会影响其他正常运行的goroutine继续工作,并且要对资源进行合理管理,说明设计思路并给出关键代码示例。
37.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用defer和recover:在每个goroutine内部使用defer关键字注册一个函数,在这个函数中使用recover来捕获panic。这样即使某个goroutine发生panic,也能被捕获并处理,避免整个程序崩溃。
  2. 资源管理:对于共享资源,使用sync包中的工具,如sync.Mutex来保证在多个goroutine访问时的数据一致性。同时,在defer中确保释放任何已获取的资源,如文件描述符等。

关键代码示例

package main

import (
    "fmt"
    "sync"
)

// 模拟一个可能会panic的函数
func riskyFunction(id int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("Goroutine %d panicked: %v\n", id, r)
        }
    }()

    // 模拟可能会导致panic的操作
    if id == 3 {
        panic("Simulated panic in goroutine 3")
    }
    fmt.Printf("Goroutine %d is working normally\n", id)
}

func main() {
    var wg sync.WaitGroup
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            riskyFunction(id)
        }(i)
    }
    wg.Wait()
    fmt.Println("All goroutines have finished")
}

在上述代码中:

  1. riskyFunction函数模拟了可能会发生panic的操作。通过deferrecover,当panic发生时,能捕获并打印出相关信息,而不会影响其他goroutine。
  2. main函数中,启动了5个goroutine,每个goroutine都调用riskyFunction,并使用sync.WaitGroup来等待所有goroutine完成。这样确保了所有goroutine都执行完毕后main函数才结束。