Go 特别检查超时错误

Go 特别检查超时错误,go,Go,在调用Web服务时,我使用以下方法检查超时,但我想特别检查是否返回超时错误。我该怎么做呢 我有这个: // Timeout type Timeout struct { Connect time.Duration ReadWrite time.Duration } // TimeoutDialer func TimeoutDialer(timeout *Timeout) func(net, addr string) (c net.Conn, err error) {

在调用Web服务时,我使用以下方法检查超时,但我想特别检查是否返回超时错误。我该怎么做呢

我有这个:

// 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),
        },
    }
}

您需要
net.Error
接口


请注意,类型断言
err.(net.Error)
将正确处理
nil
情况,如果
nil
作为错误返回,则
ok
值将返回false,从而使
超时
检查短路。

从go1.6开始,所有超时错误应符合
net.Error
,并正确设置
Timeout()。您只需检查以下各项:

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

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

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

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")
}

您只需将错误传递给,如果是net/http返回的超时,则返回true

func IsTimeout(错误)bool

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


不幸的是,正在尝试响应,err:=client.Do(req)if e,ok:=err.(net.Error);ok&&e.Timeout(){//这是一个超时fmt.Println(“Timeout”)return}
没有给我任何信息:那么你确定这是一个超时错误吗?如果出现错误,您可能需要添加一个
else!=nil
检查以覆盖非超时错误。我将超时(maxwait)设置为2秒,在这之后,一个php脚本在某处睡眠10秒(因此这应该是一个超时),返回的错误是:Get:read tcp 192.168.33.10:80:I/o timeout我不确定,
DialTimeout
如果失败,应该返回某种类型的
net.Error
。我试图阅读
net
包的源代码,但不幸的是,低级网络代码是特定于系统的,因此很难找到返回内容的证据,因为它隐藏在不同文件中的30个函数调用中。另一种检查方法是使用os.IsTimeout()函数。在这里可以找到一个工作程序-对不起,我应该声明一个
net.Error
,因为您可以得到不是操作错误的超时。因此,使用http.Client.Timeout[go1.3+]无法检查错误是否是来自传输的超时。CancelRequest?有关于这个的错误报告吗?对我来说,这条消息完全让人困惑。忘了提一下,如果你要设置连接的绝对截止日期,你应该在传输中关闭Keepalive。否则,在重复使用连接时,您可能会面临超时的风险。这应该是公认的答案-这是最简单、最惯用的方法。尽管我很欣赏您的评论,“最惯用的方法”不是也永远不应该被接受为技术原因。然而,简单是更好的:)很多人(包括我自己)通过搜索互联网学习围棋(和其他语言),他们应该被告知做某事的惯用方法,以便更恰当地学习这门语言。一个围棋专家看了这篇文章,马上就会知道哪些答案是他需要的。“惯用围棋”只不过是一种风格,而且在这方面非常教条。事实上,这通常是一种不可知论的糟糕做法。在编程中,正确的方法很可能是完全不依赖语言的。为工作使用正确的工具,而不是一群纯粹主义者让你做的事情。
if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
    fmt.Println("Could be from a Transport.CancelRequest")
}