我有一个基本的HTTP服务器,它接受请求并从数据存储中返回数据。
每个HTTP请求都执行以下操作:
这是基本的伪代码:
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)
}
我的问题是,因为上下文可能会因为超出截止日期或客户端取消请求而随时完成,我目前的方法是否适合在多个地方处理此问题或是否有更优雅的解决方案?
答案 0 :(得分:0)
return
<- ctx.Done()
req.ctx.Done()
,因此您可以完全删除第一个select {}
语句,然后只发布到数据请求通道。在请求发布前很早就完成上下文的情况下,不确定性能命中...