MST

星途 面试题库

面试题:Go中如何使用context来管理goroutine生命周期

请简述在Go语言中,如何利用context包来优雅地管理goroutine的生命周期,包括创建context、传递context以及在goroutine中如何根据context的信号进行相应的操作。请举例说明。
12.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,context包用于管理goroutine的生命周期,以下为具体操作及示例:

创建context

  1. 创建背景context

    • context.Background() 用于创建一个空的上下文,通常作为所有上下文的根。
    • context.TODO() 用于当不确定使用何种上下文时的占位符。
  2. 创建可取消的context

    • context.WithCancel(parent context.Context):创建一个可取消的上下文,返回一个新的上下文和取消函数。当调用取消函数时,新的上下文会收到取消信号。
    • context.WithDeadline(parent context.Context, deadline time.Time):创建一个带有截止时间的上下文,到截止时间时,上下文会自动取消。
    • context.WithTimeout(parent context.Context, timeout time.Duration):创建一个带有超时时间的上下文,经过指定的超时时间后,上下文会自动取消。

传递context

  1. 通过函数参数传递:在调用goroutine的函数中,将context作为参数传递进去。这样可以确保所有相关的goroutine共享相同的上下文,从而实现统一的生命周期管理。

在goroutine中根据context信号操作

  1. 监听取消信号:在goroutine内部,使用select语句监听context.Done()通道。当该通道接收到数据时,意味着上下文被取消,goroutine应该进行清理工作并退出。

示例代码

package main

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

func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("收到取消信号,退出goroutine")
            return
        default:
            fmt.Println("工作中...")
            time.Sleep(1 * time.Second)
        }
    }
}

func main() {
    // 创建可取消的context
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel() // 确保在函数结束时取消,防止资源泄漏

    // 启动goroutine
    go worker(ctx)

    // 主goroutine等待一段时间,模拟其他工作
    time.Sleep(5 * time.Second)
    fmt.Println("主goroutine结束")
}

在上述示例中,首先创建了一个带有3秒超时的上下文ctx和取消函数cancelworker函数在goroutine中运行,通过select监听ctx.Done()通道。当超时时间到或者手动调用cancel函数时,ctx.Done()通道会收到数据,worker函数收到取消信号后清理并退出。