具体检查超时错误

Mar*_*ers 29 go

我在调用webservice时使用以下内容检查超时,但我想特别检查是否返回了超时错误.我该怎么做: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),
        },
    }
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*imB 62

从go1.6开始,所有来自超时的错误都应该net.ErrorTimeout()正确设置一致.您需要检查的是:

if err, ok := err.(net.Error); ok && err.Timeout() {
Run Code Online (Sandbox Code Playgroud)

在旧版本中,通过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")
    }
}
Run Code Online (Sandbox Code Playgroud)

使用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")
}
Run Code Online (Sandbox Code Playgroud)


Jim*_*mbo 17

您可以简单地将错误传递给os.IsTimeout(),如果它是 net/http 返回的超时,那么它将返回 true。

func IsTimeout(err error) bool

IsTimeout 返回一个布尔值,指示是否已知错误以报告超时发生。

  • 这应该是公认的答案 - 这是最简单、最惯用的方法。 (6认同)
  • 请务必阅读更新的文档:`此函数早于错误。Is,并且错误是否指示超时的概念可能不明确。例如,Unix 错误 EWOULDBLOCK 有时指示超时,有时则不指示超时。新代码应该使用错误。Is 具有适合返回错误的调用的值,例如 os.ErrDeadlineExceeded。 (2认同)

Lin*_*ope 14

你想要的net.Error界面.http://golang.org/pkg/net/#Error

if e,ok := err.(net.Error); ok && e.Timeout() {
    // This was a timeout
} else if err != nil {
    // This was an error, but not a timeout
}
Run Code Online (Sandbox Code Playgroud)

请注意,类型断言err.(net.Error)将正确处理nil大小写,ok如果nil作为错误返回,则返回false,从而使Timeout检查短路.

  • 另一种检查方法是使用 os.IsTimeout() 函数。可以在此处找到工作程序 - https://golangbyexample.com/net-http-timeout/ (3认同)