一尘不染

具体检查超时错误

go

调用Web服务时,我使用以下方法检查超时,但是我想专门检查是否返回超时错误。我该怎么做:S

我有这个:

// Timeout
type Timeout struct {
    Connect   time.Duration
    ReadWrite time.Duration
}

// TimeoutDialer
func TimeoutDialer(timeout *Timeout) func(net, addr string) (c net.Conn, err error) {
    return func(netw, addr string) (net.Conn, error) {    
        conn, err := net.DialTimeout(netw, addr, timeout.Connect)
        if err != nil {
            return nil, err
        }
        conn.SetDeadline(time.Now().Add(timeout.ReadWrite))
        return conn, nil
    }
}

// HttpClient
func HttpClient(config Config) *http.Client {
    to := &Timeout{
        Connect:   time.Duration(config.MaxWait) * time.Second,
        ReadWrite: time.Duration(config.MaxWait) * time.Second,
    }

    return &http.Client{
        Transport: &http.Transport{
            Dial: TimeoutDialer(to),
        },
    }
}

阅读 145

收藏
2020-07-02

共1个答案

一尘不染

作为go1.6的,从超时所有错误应符合net.ErrorTimeout()正确设置。您需要检查的只是:

if err, ok := err.(net.Error); ok && err.Timeout() {

在旧版本中,通过http包检查超时更为困难。

  • *net.OpError如果您在基础连接上设置了“截止日期”,则可以使用Timeout()获得一个。
  • 您可以获得一个tlsHandshakeTimeoutError(显然不会导出)实现该net.Error接口的文件。
  • url.Error如果url包内有问题(初始连接期间超时),则可以获取,
  • 如果您用http.Client.Timeout[go1.3 +](调用Transport.CancelRequest)设置了超时设置,则可能会出现“使用封闭的网络连接”错误。从go1.5开始,将正确设置Timeout属性。

您可以net.Error使用类型开关检查a :

switch err := err.(type) {
case net.Error:
    if err.Timeout() {
        fmt.Println("This was a net.Error with a Timeout")
    }
case *url.Error:
    fmt.Println("This is a *url.Error")
    if err, ok := err.Err.(net.Error); ok && err.Timeout() {
        fmt.Println("and it was because of a timeout")
    }
}

当go <1.5时,您将需要检查错误字符串是否http.Client超时:

if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
    fmt.Println("Could be from a Transport.CancelRequest")
}
2020-07-02