MST

星途 面试题库

面试题:Go中Goroutine生命周期管理的资源释放

当一个goroutine被取消时,假设它持有数据库连接等资源,如何优雅地在goroutine生命周期结束时释放这些资源,同时结合`context`和`defer`语句进行说明,并给出一个简单示例。
40.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 使用contextdefer释放资源的原理
    • context用于在多个goroutine之间传递取消信号。它提供了一种机制,允许父goroutine取消子goroutine,子goroutine可以监听这个取消信号。
    • defer语句用于延迟执行函数调用。在goroutine结束时,defer语句会按照后进先出(LIFO)的顺序执行,这非常适合用于资源清理工作。
  2. 示例代码
package main

import (
    "context"
    "fmt"
    "time"
)

// 模拟数据库连接结构体
type DatabaseConnection struct {
    // 这里可以添加数据库连接相关的字段
}

// 模拟关闭数据库连接的方法
func (db *DatabaseConnection) Close() {
    fmt.Println("Closing database connection")
}

func worker(ctx context.Context) {
    // 模拟获取数据库连接
    db := &DatabaseConnection{}
    // 使用defer在函数结束时关闭数据库连接
    defer db.Close()

    for {
        select {
        case <-ctx.Done():
            // 当收到取消信号时,退出循环
            fmt.Println("Received cancel signal, cleaning up")
            return
        default:
            // 模拟工作
            fmt.Println("Working...")
            time.Sleep(1 * time.Second)
        }
    }
}

你可以使用以下方式调用这个函数:

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    go worker(ctx)

    // 主goroutine等待一段时间
    time.Sleep(5 * time.Second)
}

在这个示例中:

  • worker函数使用context.Context来监听取消信号。
  • 通过defer语句确保在worker函数结束时,无论正常结束还是因为取消而结束,数据库连接都会被关闭。
  • main函数中,通过context.WithTimeout创建一个带有超时的context,并在defer中调用cancel函数,确保资源能够被及时释放。