MST

星途 面试题库

面试题:Go语言中Context的主要作用及常见使用场景

请简述Go语言中Context的主要作用,并且列举至少三个常见的应用场景。同时说明在这些场景下,Context是如何帮助管理和控制goroutine的。
46.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Go语言中Context的主要作用

Context主要用于在多个goroutine之间传递截止时间、取消信号和其他请求范围的值,以便在整个应用程序中进行协作式取消和控制。它可以帮助我们更好地管理goroutine的生命周期,避免资源泄漏,并在特定条件下优雅地停止goroutine。

常见应用场景及Context对goroutine的管理和控制

  1. 请求取消
    • 场景:当一个HTTP请求被取消或超时,相关的所有goroutine也应该被取消,以避免不必要的计算和资源浪费。
    • 管理和控制方式:在HTTP服务器处理请求时,将context.Context从顶层函数传递到所有启动的goroutine中。当请求取消时,context.Context会发出取消信号,所有接收该context.Context的goroutine可以通过检查ctx.Done()通道是否关闭来决定是否停止执行。例如:
func handleRequest(ctx context.Context, w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()

    go func() {
        select {
        case <-ctx.Done():
            return
        // 业务逻辑
        }
    }()
}
  1. 设置截止时间
    • 场景:某个操作需要在指定时间内完成,比如数据库查询操作,若超过设定时间还未完成则应取消操作。
    • 管理和控制方式:通过context.WithTimeoutcontext.WithDeadline创建带有截止时间的context.Context。在goroutine中,使用select语句监听ctx.Done()通道和业务逻辑的通道。当截止时间到达,ctx.Done()通道会关闭,goroutine可以据此停止执行。例如:
func databaseQuery(ctx context.Context) {
    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()

    resultCh := make(chan string)
    go func() {
        // 模拟数据库查询操作
        time.Sleep(10 * time.Second)
        resultCh <- "query result"
    }()

    select {
    case result := <-resultCh:
        fmt.Println(result)
    case <-ctx.Done():
        fmt.Println("query timeout")
    }
}
  1. 传递请求范围的值
    • 场景:在处理HTTP请求时,可能需要在多个中间件和业务逻辑函数组成的调用链中传递一些与请求相关的值,如用户认证信息等。
    • 管理和控制方式:使用context.WithValue创建携带值的context.Context,并将其传递给后续的函数和goroutine。在需要使用该值的地方,通过ctx.Value(key)获取值。例如:
func middleware(ctx context.Context) context.Context {
    ctx = context.WithValue(ctx, "userID", "12345")
    return ctx
}

func handle(ctx context.Context) {
    userID := ctx.Value("userID")
    fmt.Println("User ID:", userID)
}