Mam pewien kod (patrz poniżej) napisany w Go, który ma "wysyłać" żądania HTTP, i zestawiać/agregować szczegóły z powrotem.Jak radzić sobie z błędami limitu czasu HTTP i uzyskiwać dostęp do kodów statusu w golang
I'm new to golang and so expect me to be a nOOb and my knowledge to be limited
Wyjście programu jest obecnie coś takiego:
{
"Status":"success",
"Components":[
{"Id":"foo","Status":200,"Body":"..."},
{"Id":"bar","Status":200,"Body":"..."},
{"Id":"baz","Status":404,"Body":"..."},
...
]
}
Jest tam lokalny serwer, który bieg jest celowo powolne (śpi przez 5 sekund, a następnie zwraca odpowiedź). Ale mam też inne witryny (patrz kod poniżej), które czasami wywołują również błąd (jeśli błąd, to jest w porządku).
Problem jaki mam w tej chwili, to jak najlepiej radzić sobie z tymi błędami, aw szczególności z błędami "timeoutowymi"; w którym nie jestem pewien, jak rozpoznać, czy awaria jest przekroczeniem limitu czasu, czy innym błędem?
W tej chwili pojawia się błąd koc cały czas (! Nadzieją timeout)
Get http://localhost:8080/pugs: read tcp 127.0.0.1:8080: use of closed network connection
Gdzie http://localhost:8080/pugs
będzie na ogół adres URL, który nie powiodło się. Ale jak widać z kodu (poniżej), nie jestem pewien, jak ustalić kod błędu jest związany z przekroczeniem limitu czasu, ani jak uzyskać dostęp do kodu statusu odpowiedzi (obecnie ustawiam go tylko na 404
, ale oczywiście to nie jest w porządku - jeśli serwer popełnił błąd, oczekiwałbym czegoś w rodzaju kodu statusu 500
i oczywiście chciałbym to odzwierciedlić w zagregowanej odpowiedzi, którą odesłałem).
Pełny kod można zobaczyć poniżej. Każda pomoc doceniona.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"sync"
"time"
)
type Component struct {
Id string `json:"id"`
Url string `json:"url"`
}
type ComponentsList struct {
Components []Component `json:"components"`
}
type ComponentResponse struct {
Id string
Status int
Body string
}
type Result struct {
Status string
Components []ComponentResponse
}
var overallStatus string = "success"
func main() {
var cr []ComponentResponse
var c ComponentsList
b := []byte(`{"components":[{"id":"local","url":"http://localhost:8080/pugs"},{"id":"google","url":"http://google.com/"},{"id":"integralist","url":"http://integralist.co.uk/"},{"id":"sloooow","url":"http://stevesouders.com/cuzillion/?c0=hj1hfff30_5_f&t=1439194716962"}]}`)
json.Unmarshal(b, &c)
var wg sync.WaitGroup
timeout := time.Duration(1 * time.Second)
client := http.Client{
Timeout: timeout,
}
for i, v := range c.Components {
wg.Add(1)
go func(i int, v Component) {
defer wg.Done()
resp, err := client.Get(v.Url)
if err != nil {
fmt.Printf("Problem getting the response: %s\n", err)
cr = append(cr, ComponentResponse{
v.Id,
404,
err.Error(),
})
} else {
defer resp.Body.Close()
contents, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Problem reading the body: %s\n", err)
}
cr = append(cr, ComponentResponse{
v.Id,
resp.StatusCode,
string(contents),
})
}
}(i, v)
}
wg.Wait()
j, err := json.Marshal(Result{overallStatus, cr})
if err != nil {
fmt.Printf("Problem converting to JSON: %s\n", err)
return
}
fmt.Println(string(j))
}
Najprawdopodobniej niezwiązane Twój problem, ale masz wyścig danych dołączony do 'cr'. Nie można zapisać tej samej zmiennej z wielu goroutin bez synchronizacji. Możesz zbudować/uruchomić za pomocą [detektora wyścigów] (https://blog.golang.org/race-detector). –
Dzięki za komentarz. Spróbuję wykorzystać kanały zamiast + Zbadam ten wykrywacz wyścigów :-) – Integralist
Jeśli wywołanie klienta zwróci błąd, nie ma kodu statusu, ponieważ nie było pełnego żądania http. Nie można wiele zrobić z błędem w tym momencie, ale w wersji 1.5 klient.Timeout przynajmniej zwróci lepszy komunikat w sieci. Błąd. – JimB