使用HTTP请求上下文管理通道

5

我有一个基本的HTTP服务器,可以接受请求并从数据存储中返回数据。

每个HTTP请求都会执行以下操作:

  1. 创建超时上下文
  2. 创建读取请求(自定义类型)
  3. 将读取请求推送到通道中
  4. 等待响应并提供数据

以下是基本伪代码:

package main

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

type dataRequest struct {
    data chan string
    ctx  context.Context
}

func handler(reqStream chan dataRequest) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
        defer cancel()

        req := dataRequest{
            data: make(chan string),
            ctx:  ctx,
        }

        select {
        case reqStream <- req:
            // request pushed to que
        case <-ctx.Done():
            // don't push onto reqStream if ctx done
        }

        select {
        case <-ctx.Done():
            // don't try and serve content if ctx done
        case data := <-req.data:
            // return data to client
        }

    }
}

func main() {
    dataReqs := make(chan dataRequest)
    go func() {
        for {
            select {
            case req := <-dataReqs:
                select {
                case <-req.ctx.Done():
                    // don't push onto data channel if ctx done
                case req.data <- "some data":
                    // get data from store
                }
            }
        }
    }()
    http.HandleFunc("/", handler(dataReqs))
    http.ListenAndServe(":8080", nil)
}

我的问题是,由于截止日期超过或客户取消请求,上下文可能随时结束,那么我目前的处理方法在多个地方处理是否正确,还是有更加优雅的解决方案?
1个回答

0

我认为这会起作用。 几点意见 -

  1. <- ctx.Done() 的第一个 case 中,你可以使用 return
  2. 在数据存储处理程序中,你已经在等待 req.ctx.Done(),因此你可以完全删除第一个 select {} 语句,并只将请求发布到数据请求频道。对于即使在请求发布之前上下文就已经完成的罕见情况,不确定是否存在性能问题...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接