MST

星途 面试题库

面试题:Go中context设计目的在简单Web服务场景的实现路径

假设你正在开发一个简单的Go Web服务,该服务会调用外部API获取数据。请描述如何使用context来实现Go context设计目的,比如控制请求的生命周期,处理超时等,给出关键代码示例并解释。
20.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

控制请求生命周期与处理超时的实现

在Go中,context包用于在多个goroutine之间传递截止时间、取消信号等,以控制请求的生命周期和处理超时。

  1. 关键代码示例
package main

import (
    "context"
    "fmt"
    "net/http"
    "time"
)

// 模拟调用外部API的函数
func callExternalAPI(ctx context.Context) (string, error) {
    // 模拟一个需要一定时间的操作
    select {
    case <-time.After(2 * time.Second):
        return "data from external API", nil
    case <-ctx.Done():
        return "", ctx.Err()
    }
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 创建带有超时的context
        ctx, cancel := context.WithTimeout(r.Context(), 1*time.Second)
        defer cancel()

        data, err := callExternalAPI(ctx)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        fmt.Fprintf(w, "Response: %s", data)
    })

    fmt.Println("Server is running on http://localhost:8080")
    http.ListenAndServe(":8080", nil)
}
  1. 代码解释
    • 创建带超时的contextctx, cancel := context.WithTimeout(r.Context(), 1*time.Second) 这行代码基于传入的请求上下文 r.Context() 创建了一个新的带有1秒超时的上下文 ctx,同时返回一个取消函数 cancel。在函数结束时,通过 defer cancel() 调用取消函数,以确保在函数返回前释放相关资源。
    • 模拟外部API调用: 在 callExternalAPI 函数中,使用 select 语句监听两个通道。time.After(2 * time.Second) 模拟外部API调用需要2秒时间完成。ctx.Done() 通道用于监听上下文是否被取消(比如超时)。如果 ctx.Done() 通道接收到信号,说明上下文已被取消,函数返回错误。
    • 处理结果: 在 main 函数的HTTP处理函数中,调用 callExternalAPI(ctx) 获取数据。如果调用过程中出现错误(如超时),则返回HTTP 500错误。否则,将获取到的数据返回给客户端。

通过这种方式,context 实现了对请求生命周期的控制以及超时处理,确保在规定时间内完成操作或及时取消不必要的任务。