Подтвердить что ты не робот

В частности, проверьте ошибку тайм-аута

Я использую следующее для проверки тайм-аутов при вызове веб-службы, но я бы хотел проверить, действительно ли возникла ошибка тайм-аута. Как это сделать: 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),
        },
    }
}
4b9b3361

Ответ 1

Начиная с go1.6, все ошибки от тайм-аутов должны соответствовать net.Error с Timeout(). Все, что вам нужно проверить, это:

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 с помощью переключателя типа:

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

Ответ 2

Вам нужен интерфейс 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
}

Обратите внимание, что утверждение типа err.(net.Error) корректно обрабатывает случай nil и возвращает false для значения ok, если nil возвращается как ошибка, замыкающая проверку Timeout.

Ответ 3

Вы можете просто передать сообщение об ошибке в os.IsTimeout(), и если в качестве таймаута возвращается net/http, то он вернет true.

func IsTimeout(err error) bool

IsTimeout возвращает логическое значение, указывающее, известна ли ошибка, чтобы сообщить, что произошел тайм-аут.