MST

星途 面试题库

面试题:Go语言中Context如何在多个Goroutine间传递

请描述在Go语言里,使用Context实现Goroutine优雅退出时,如何将Context在多个Goroutine之间有效传递,并说明这样做的好处。同时,给出一个简单的代码示例展示这种传递过程。
15.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

1. Context在多个Goroutine之间有效传递的方式

在Go语言中,通常将Context作为参数在函数调用链中传递,从而将其传递到各个需要它的Goroutine。一般在启动新的Goroutine时,将Context作为参数传递进去。

2. 这样做的好处

  • 控制并发:可以通过Context统一控制多个Goroutine的生命周期,例如在程序退出、超时等情况下,能够同时通知所有相关的Goroutine进行清理并退出。
  • 资源管理:方便进行资源的清理工作,比如关闭数据库连接、文件句柄等,避免资源泄漏。
  • 超时处理:可以设置操作的超时时间,防止Goroutine长时间阻塞导致程序响应变慢。

3. 代码示例

package main

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

func worker(ctx context.Context, id int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("Worker %d received termination signal\n", id)
            return
        default:
            fmt.Printf("Worker %d is working\n", id)
            time.Sleep(1 * time.Second)
        }
    }
}

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

    for i := 1; i <= 3; i++ {
        go worker(ctx, i)
    }

    time.Sleep(5 * time.Second)
    fmt.Println("Main function exiting")
}

在上述代码中:

  • context.WithTimeout创建了一个带有超时的Context,超时时间为3秒。
  • cancel函数用于手动取消Context,这里通过defer确保在函数结束时调用,以释放相关资源。
  • worker函数接收Context作为参数,通过select监听ctx.Done()通道,当接收到信号时,代表Context被取消,Goroutine执行清理并退出。