MST

星途 面试题库

面试题:Go中context辅助函数在HTTP请求处理中的使用边界

在Go的HTTP服务器开发中,使用context辅助函数来处理请求上下文。假设你有一个简单的HTTP处理函数,需要在其中调用多个子函数,这些子函数可能会发起网络请求或执行数据库查询。请描述在这种场景下,context辅助函数(如context.WithTimeout、context.WithCancel等)的使用边界在哪里,以及如何正确传递context以确保资源的合理释放和请求的及时取消。
11.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

使用边界

  1. WithTimeout
    • 边界:用于设置一个操作的最长执行时间。适用于子函数中发起网络请求或数据库查询时,限定这些操作不能无限制等待。例如,当调用数据库查询函数时,如果数据库出现异常长时间响应,WithTimeout 可以避免整个请求一直等待,而是在超时后快速返回,释放相关资源。
    • 注意:超时时间的设置要根据实际业务场景合理调整。设置过短可能导致正常操作也被超时中断,设置过长则可能无法及时释放资源。
  2. WithCancel
    • 边界:适用于需要根据某些条件手动取消操作的场景。比如在子函数执行过程中,根据接收到的外部信号(如另一个 HTTP 请求通知),提前终止当前正在执行的网络请求或数据库查询等操作。
    • 注意:要确保取消操作能正确传递到所有相关子函数,避免部分子函数继续执行不必要的操作。

正确传递context

  1. 顶层处理函数
    • 在 HTTP 处理函数入口处创建 context。例如,使用 context.WithTimeout 创建一个带有超时的 context:
    func handler(w http.ResponseWriter, r *http.Request) {
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
        // 调用子函数并传递 ctx
        err := subFunction1(ctx)
        if err!= nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
    }
    
  2. 子函数传递
    • 每个子函数都应该接受 context.Context 作为参数。例如:
    func subFunction1(ctx context.Context) error {
        // 发起网络请求或数据库查询
        req, err := http.NewRequestWithContext(ctx, "GET", "http://example.com", nil)
        if err!= nil {
            return err
        }
        resp, err := http.DefaultClient.Do(req)
        if err!= nil {
            return err
        }
        defer resp.Body.Close()
        // 处理响应
        return nil
    }
    
    • 这样,当顶层 context 取消(超时或手动取消)时,所有接受该 context 的子函数都能感知并及时取消正在进行的操作,如网络请求被取消,数据库查询被中断,从而确保资源的合理释放和请求的及时取消。