MST

星途 面试题库

面试题:Go并发程序中异常处理与资源释放的协调

在一个Go并发程序中,有多个goroutine在操作共享资源(例如文件描述符、数据库连接等),当其中一个goroutine发生异常时,不仅要捕获处理异常,还需要确保所有相关的共享资源能正确释放,避免资源泄漏。请描述整体设计思路并给出关键代码示例。
20.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用defer和recover:在每个goroutine中使用defer语句来确保无论是否发生异常,资源都能被正确释放。通过recover函数捕获异常,避免异常导致程序崩溃。
  2. 资源管理:对于共享资源(如文件描述符、数据库连接),可以封装在一个结构体中,在结构体的方法中进行资源的获取和释放操作。
  3. 同步机制:使用sync.Mutexsync.RWMutex来保护对共享资源的访问,避免竞态条件。

关键代码示例

package main

import (
    "fmt"
    "sync"
)

// 假设这是一个共享资源,例如数据库连接
type DatabaseConnection struct {
    // 实际连接相关的字段
    connection string
    mu         sync.Mutex
}

// 获取连接
func (db *DatabaseConnection) GetConnection() string {
    db.mu.Lock()
    defer db.mu.Unlock()
    // 实际获取连接的逻辑
    return "connection string"
}

// 释放连接
func (db *DatabaseConnection) ReleaseConnection() {
    db.mu.Lock()
    defer db.mu.Unlock()
    // 实际释放连接的逻辑
    fmt.Println("Connection released")
}

func worker(db *DatabaseConnection, wg *sync.WaitGroup) {
    defer wg.Done()
    // 获取资源
    conn := db.GetConnection()
    defer db.ReleaseConnection()

    // 模拟可能发生异常的操作
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()

    // 模拟异常
    panic("Some error occurred")

    fmt.Println("Using connection:", conn)
}

func main() {
    var wg sync.WaitGroup
    db := DatabaseConnection{}

    // 启动多个goroutine
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go worker(&db, &wg)
    }

    wg.Wait()
    fmt.Println("All workers completed")
}

在上述代码中:

  • DatabaseConnection结构体封装了共享资源(数据库连接)以及用于保护资源访问的sync.Mutex
  • worker函数是每个goroutine执行的逻辑,通过defer确保在函数结束时释放资源,无论是否发生异常。
  • recover函数捕获可能发生的异常,避免程序崩溃。