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