dongxian7489 2016-02-12 09:11
浏览 13

如何处理客户端超时错误? [重复]

This question already has an answer here:

I am trying to make a HTTP call to a server and am using a 10 second client timeout. The current (incorrect) way of how I am handling it is like this:

package checks

import "net/http"
import "fmt"
import "log"
import "time"
import "strings"

var client = &http.Client{Timeout: 10 * time.Second}

func HttpCheck(url string) (string, error) {
    log.Printf("initiating http get to %s
", url)
    resp, err := client.Get(url)

    if err != nil {
        if strings.Contains(err.Error(), "Client.Timeout") {
            return "loading", nil
        } else {
            log.Printf("error while getting url : %s
", err.Error())
            return "", err
        }
    }
    defer resp.Body.Close()
    if resp.StatusCode != 200 {
        log.Printf("got a non 200 response: %d", resp.StatusCode)
        return "", fmt.Errorf("Server returned non 200 status: %d", resp.StatusCode)
    }
    log.Println("all is well, returning a success")
    return "up", nil
}

The actual error thrown by Go httpError is unexported.

How do I reliably handle a client timeout?

</div>
  • 写回答

1条回答 默认 最新

  • duanmiyang6201 2016-02-12 10:32
    关注

    Given the current state of timeout error handling in the standard library (which will hopefully be improved soon, normally as of the upcoming 1.6 version), you can fall back on a way to check for timeout conditions using goroutines, channels and timers.

    For example:

    func httpCheck(url string) (string, error) {
        // channels for result, and error
        responseChan := make(chan string, 1)
        errChan := make(chan error, 1)
    
        timeout := 30 * time.Second
    
        // run http get asynchronously
        go func() {
            client := &http.Client{
                Timeout: timeout + 5.Second, // use a longer timeout so the goroutine does not block forever
            }
    
            resp, err := client.Get(url)
            if err != nil {
                errChan <- err
                return
            }
    
            defer resp.Body.Close()
    
            if resp.StatusCode != http.StatusOK {
                errChan <- fmt.Errorf("Server returned non 200 status: %d", resp.StatusCode)
                return
            }
            responseChan <- "up"
        }()
    
        // wait for the first thing to happen, either
        // an error, a timeout, or a result
        select {
        case err := <-errChan:
            return nil, err
        case <-time.After(timeout):
            return nil, errors.New("timeout")
        case result := <-responseChan:
            return result, nil
        }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?