MST
星途 面试题库

面试题:Go中panic和recover与并发编程的深度结合

在一个高并发的Go程序中,多个goroutine同时访问共享资源。如果其中一个goroutine由于资源竞争导致数据不一致进而触发panic,如何使用recover来保证其他goroutine继续正常运行,并且能够优雅地处理该错误,同时确保程序不会发生内存泄漏或其他未定义行为?请详细阐述设计思路并给出核心代码片段。
32.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用defer和recover:在每个可能引发资源竞争导致panic的goroutine中,使用defer语句注册一个函数,在该函数中使用recover来捕获panic。
  2. 错误处理:捕获到panic后,记录错误信息,确保不影响其他goroutine的正常运行。
  3. 防止内存泄漏:确保所有的资源(如文件描述符、网络连接等)都能正确关闭或释放。

核心代码片段

package main

import (
    "fmt"
    "log"
)

// 共享资源
var sharedResource int

func worker(id int) {
    defer func() {
        if r := recover(); r != nil {
            // 捕获panic并记录错误
            log.Printf("Goroutine %d panicked: %v", id, r)
        }
    }()

    // 模拟资源竞争
    for i := 0; i < 10; i++ {
        sharedResource++
        // 模拟可能引发panic的操作
        if sharedResource > 10 {
            panic("Data inconsistency")
        }
        fmt.Printf("Goroutine %d: sharedResource = %d\n", id, sharedResource)
    }
}

func main() {
    // 启动多个goroutine
    for i := 0; i < 3; i++ {
        go worker(i)
    }

    // 防止主线程退出
    select {}
}

在上述代码中:

  1. worker函数中使用defer注册了一个匿名函数,该函数使用recover捕获可能的panic。
  2. 如果捕获到panic,使用log.Printf记录错误信息,这样其他goroutine不会受到影响。
  3. 代码中虽然没有显式处理资源释放(因为示例简单),但在实际应用中,打开的资源应在defer中正确关闭,以防止内存泄漏。例如,如果有文件操作,在defer中调用file.Close()