dtng25909 2018-02-03 11:59
浏览 43
已采纳

在golang中的X ms之后以编程方式关闭http连接

I'm doing X parallel http requests and when one of them does not respond in X ms (imagine is 100ms) or less I want to cut this connection. The code I wrote does not seem to work so, how can I cut the connection and get the response as nil?

This is my sample code:

cx, cancel := context.WithCancel(context.Background())
ch := make(chan *HttpResponse)
var responses []*HttpResponse

timeout := 1.000 //1ms for testing purposes
var client = &http.Client{
    Timeout: 1 * time.Second,
}

startTime := time.Now()
for _, url := range urls {
    go func(url string) {
        fmt.Printf("Fetching %s 
", url)
        req, _ := http.NewRequest("POST", url, bytes.NewReader(request)) //request is json string
        req.WithContext(cx)
        resp, err := client.Do(req)
        ch <- &HttpResponse{url, resp, err}
        var timeElapsed = time.Since(startTime)
        msec := timeElapsed.Seconds() * float64(time.Second/time.Millisecond)
        if msec >= timeout {
            cancel()
        }
        if err != nil && resp != nil && resp.StatusCode == http.StatusOK {
            resp.Body.Close()
        }
    }(url)
}

for {
    select {
    case r := <-ch:
        fmt.Printf("%s was fetched
", r.Url)
        if r.Err != nil {
            fmt.Println("with an error", r.Err)
        }
        responses = append(responses, r)
        if len(responses) == len(*feeds) {
            return responses
        }
    case <-time.After(100):
        //Do something
    }
}
  • 写回答

1条回答 默认 最新

  • dry69034 2018-02-03 12:15
    关注

    Your code waits until a requests finishes (and get a resposne or an error), and then calculate the time passed, and if it was longer than the time expect, your code would cancel all the requests.

        req, _ := http.NewRequest("POST", url, bytes.NewReader(request)) //request is json string
        req.WithContext(cx) //Here you use a common cx, which all requests share.
        resp, err := client.Do(req) //Here the request is being sent and you wait it until done.
        ch <- &HttpResponse{url, resp, err}
        var timeElapsed = time.Since(startTime)
        msec := timeElapsed.Seconds() * float64(time.Second/time.Millisecond)
        if msec >= timeout {
            cancel() //here you cancel all the requests.
        }
    

    The fix is to utilize the context package right.

        req, _ := http.NewRequest("POST", url, bytes.NewReader(request)) //request is json string
        ctx,cancel := context.WithTimeout(request.Context(),time.Duration(timeout)*time.Millisecond)
        resp,err:=client.Do(req.WithContext(ctx))
        defer cancel()
    

    With that, you will get a nil resp (and an error) and get the connection cut when time out.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题 别拿AI回答
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?