golang http server如何设置request的context超时

CodingCode · · 1699 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

main函数

func main() {
    address := fmt.Sprintf("%s:%d", "0.0.0.0", 8080)
    router  := mux.NewRouter().StrictSlash(true)

    router.HandleFunc("/api/hello", handler)
    err := http.ListenAndServe(address, router)
    if err != nil {
        log.Panic("ListenAndServe err:", err)
    }
}

handler函数

func handler(w http.ResponseWriter, r *http.Request) {
    log.Printf("Request is coming\n")
    var userId string
    if queryParams, ok := r.URL.Query()["user"]; ok && len(queryParams) > 0 {
        userId = queryParams[0]
    }

    // handle context timeout
    var ctx context.Context
    var cancel context.CancelFunc
    if queryParams, ok  := r.URL.Query()["timeout"]; ok && len(queryParams) > 0 {
        timeout, err := time.ParseDuration(queryParams[0])
        if err != nil {
            ctx, cancel = context.WithCancel(r.Context())
        } else {
            ctx, cancel = context.WithTimeout(r.Context(), timeout)
        }
    } else {
        ctx, cancel = context.WithCancel(r.Context())
    }
    defer cancel()

    // call implementation function
    result, err := GetUser(ctx, userId)
    if err != nil {
        log.Printf("Request is return with error: %v\n", err)
        writeErrorResponse(http.StatusInternalServerError, err, w)
        return
    }

    log.Printf("Request is return with success\n")
    writeResponse(http.StatusOK, result, w)
}

在handler函数里面从r.Context生成一个新的context,并传递给功能函数GetUser(ctx context).

功能函数

func GetUser(ctx context.Context, userId string) (map[string]string, error) {
    c := make(chan interface{}, 1)

    go func() {
        time.Sleep(10 * time.Second)

        c <- "123-456-7890"
    } ()

    select {
    case <-ctx.Done():
        log.Printf("Context interrupt or timeout: %v\n", ctx.Err())
        return nil, fmt.Errorf("Context interrupt or timeout: %v", ctx.Err())
    case result := <-c:
        return map[string]string{"name":userId, "phone": result.(string)}, nil
    }
}

在功能函数里面,异步方式调用起来具体的实现功能,然后等待在ctx.Done()或者c里面有数据。

  • ctx.Done返回如果满足:
    -- client放弃请求,或者
    -- 超时,根据参数timeout设置的超时
  • c里面有数据,则表示具体的实现功能函数完成,在这里例子里是匿名函数执行返回。

使用curl工具发起client请求:

  1. curl localhost:8080/api/hello
    正常请求,10秒后返回
  2. curl localhost:8080/api/hello + ctrl-C
    用户ctrl-C杀掉curl命令
  3. curl --max-time 5 localhost:8080/api/hello
    客户端设置5秒超时

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:CodingCode

查看原文:golang http server如何设置request的context超时

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1699 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传