我正在尝试对服务器进行HTTP调用,并使用10秒的客户端超时。我正在处理它的当前(不正确)方式是这样的:
package checks
import "net/http"
import "fmt"
import "log"
import "time"
import "strings"
var client = &http.Client{Timeout: 10 * time.Second}
func HttpCheck(url string) (string, error) {
log.Printf("initiating http get to %s\n", url)
resp, err := client.Get(url)
if err != nil {
if strings.Contains(err.Error(), "Client.Timeout") {
return "loading", nil
} else {
log.Printf("error while getting url : %s\n", err.Error())
return "", err
}
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
log.Printf("got a non 200 response: %d", resp.StatusCode)
return "", fmt.Errorf("Server returned non 200 status: %d", resp.StatusCode)
}
log.Println("all is well, returning a success")
return "up", nil
}
Go httpError
引发的实际错误未导出。
如何可靠地处理客户端超时?
答案 0 :(得分:0)
鉴于标准库中的当前超时错误处理状态(有望很快得到改进,通常是即将发布的1.6版本),您可以使用goroutines,channel和timers来检查超时条件。
例如:
func httpCheck(url string) (string, error) {
// channels for result, and error
responseChan := make(chan string, 1)
errChan := make(chan error, 1)
timeout := 30 * time.Second
// run http get asynchronously
go func() {
client := &http.Client{
Timeout: timeout + 5.Second, // use a longer timeout so the goroutine does not block forever
}
resp, err := client.Get(url)
if err != nil {
errChan <- err
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
errChan <- fmt.Errorf("Server returned non 200 status: %d", resp.StatusCode)
return
}
responseChan <- "up"
}()
// wait for the first thing to happen, either
// an error, a timeout, or a result
select {
case err := <-errChan:
return nil, err
case <-time.After(timeout):
return nil, errors.New("timeout")
case result := <-responseChan:
return result, nil
}
}