douweng3564
douweng3564
2017-07-04 17:49
浏览 243
已采纳

设置内置HTTP请求超时的最佳方法

What is the best way to setup a timeout on built-in http NewRequest? Currently, I'm using http.Client.Timeout which is cover the entire exchange, but is there something better for example context.WithDeadline or context.WithTimeout. If yes how is it working, how can I setup a context.WithDeadline solution for the http.NewRequest?

There is my current solution:

func (c *Client) post(resource string, data url.Values, timeout time.Duration) ([]byte, error) {
    url := c.getURL(resource)
    client := &http.Client{
        Timeout: timeout * time.Millisecond,
    }
    req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
    if err != nil {
        return nil, err
    }
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    return ioutil.ReadAll(resp.Body)
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dqdmvg7332
    dqdmvg7332 2017-07-04 18:09
    已采纳

    Get new context from context.WithDeadline. See documentation. WithTimeout just returns WithDeadline(parent, time.Now().Add(timeout)).

    package main
    
    import (
        "context"
        "io"
        "log"
        "net/http"
        "os"
        "time"
    )
    
    func getContent(ctx context.Context) {
        req, err := http.NewRequest("GET", "http://example.com", nil)
        if err != nil {
            log.Fatal(err)
        }
        ctx, cancel := context.WithDeadline(ctx, time.Now().Add(3 * time.Second))
        defer cancel()
    
        req.WithContext(ctx)
    
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            log.Fatal(err)
        }
        defer resp.Body.Close()
        io.Copy(os.Stdout, resp.Body)
    }
    
    func main() {
        ctx := context.Background()
        getContent(ctx)
    }
    

    If you want to make cancel trigger on main:

    func main() {
        ctx := context.Background()
        ctx, cancel := context.WithCancel(ctx)
    
        sc := make(chan os.Signal, 1)
        signal.Notify(sc, os.Interrupt)
        go func(){
            <-sc
            cancel()
        }()
    
        getContent(ctx)
    }
    
    点赞 评论

相关推荐