2016-12-21 4 views
0

Ich bin ziemlich neu in der Codierung in Golang und kämpfe mit der Panik/erholen Prozess für eine schlechte URL Anfrage. Unten ist ein Skript, das eine Liste von URLs abfragt und Antworten ausgibt. Gelegentlich wird eine ungültige URL eingegeben oder ein Server ist inaktiv und die HTTP-Anforderung schlägt fehl, was zu einer Panik führt. Ich weiß nicht, wie ich mich davon erholen und weitermachen soll. Ich möchte, dass das Programm die Panik wiederherstellt, die fehlerhafte URL und den Fehler dokumentiert und die Liste der URLs fortsetzt, die die fehlgeschlagene URL und den Fehler mit dem Rest der normalen URL-Antwortdaten ausgeben.Golang http Anfrage Fehler Panik erholen

package main 

import (
    "fmt" 
    "net/http" 
) 

var urls = []string{ 
    "http://www.google.com",  //good url, 200 
    "http://www.googlegoogle.com/", //bad url 
    "http://www.zoogle.com",  //500 example 
} 

//CONCURRENT HTTP REQUESTS ------------------------------------------- 
func MakeRequest(url string, ch chan<- string) { 
    resp, err := http.Get(url) 
    if err != nil { 
     fmt.Println("Error Triggered", err) 
     ch <- fmt.Sprintf("err: %s", err) 
    } 
    ch <- fmt.Sprintf("url: %s, status: %s ", url, resp.Status) // put response into a channel 
    resp.Body.Close() 
} 

func main() { 
    output := make([][]string, 0) //define an array to hold responses 

    //PANIC RECOVER------------------------------ 
    defer func() { //catch or finally 
     if r := recover(); r != nil { //catch 
      fmt.Println("Recover Triggered: ", r) 
     } 
    }() 

    //MAKE URL REQUESTS---------------------------------------------- 
    for _, url := range urls { 
     ch := make(chan string)     //create a channel for each request 
     go MakeRequest(url, ch)     //make concurrent http request 
     output = append(output, []string{<-ch}) //append output to an array 
    } 

    //PRINT OUTPUT ---------------------- 
    for _, value := range output { 
     fmt.Println(value) 
    } 
} 

Ich bin für eine Ausgabe ähnlich:

[url: http://www.google.com, Status: 200 OK]

[url: http://www.googlegoogle.com, err: no host]

[ url: http://www.zoogle.com, Status: 500 Interner Server Fehler]

+2

Wenn Sie aus irgendeinem Grund nicht gezielt in Panik geraten, weist eine Panik auf einen Fehler in Ihrem Programm hin. Beheben Sie die Fehler, damit Sie keine Paniken mehr haben, von denen Sie wiederherstellen können. – JimB

+0

Diese Logik hilft, sieht aus wie im Falle eines Fehlers habe ich nichts "ch" für den resp.Status zu setzen. Wenn ich die Fehlerbehandlung modifiziert, stoppt die Panik und ich kann herausfinden, wie ich ansprechen soll. –

+0

kann nicht nur nil zurückgeben, wenn err nicht gleich null ist, aber hüte dich davor, dass es möglich ist, dass, wenn err nicht gleich null ist, dann nicht gleich null ist, sondern eine Panik auslöst, wenn du es dereferenzieren willst!es ist nicht speziell für diesen Funktionsaufruf so, aber die Datei walker-Schnittstelle hatte dieses Verhalten (zumindest in einer älteren Version von go), wenn err nicht Null, der andere zurückgegebene Wert ist nicht Null, aber es war ein Müllwert, der nicht dereferenziert werden kann. – Rob

Antwort

1

Dank Jim B. Ich nahm an, die Panik wurde durch die Anfrage ausgelöst, aber es war th e versuchen, "resp.Status" für eine fehlgeschlagene Anfrage zu verwenden, da sie nicht existiert. Ich änderte meine Fehlerbehandlung, um nur einen resp.Status in den "ch" zu setzen, wenn kein Fehler vorliegt. Im Falle eines Fehlers ersetze ich eine andere Antwort in das "ch" mit dem Fehlerwert. Keine Notwendigkeit, sich zu erholen, da keine Panik ausgelöst wurde.

func MakeRequest(url string, ch chan<- string) { 
    resp, err := http.Get(url) 
    if err != nil { 
     ch <- fmt.Sprintf("url: %s, err: %s ", url, err) 
    } else { 
     ch <- fmt.Sprintf("url: %s, status: %s ", url, resp.Status) // put response into a channel 
     defer resp.Body.Close() 
    } 
} 

Ausgang ist jetzt:

[url: http://www.google.com, Status: 200 OK]

[url: http://www.googlegoogle.com/, err: Get http://www.googlegoogle.com/: dial tcp: Lookup www.googlegoogle.com: nein so host]

[url: http://www.zoogle.com, Status: 500 Internal Server Error]

0

Der einzige Ort, ich würde (und tun) Stelle erholt sich: in einer "Fehlerbarriere".

Eine "Fehlerbarriere" ist der höchste verfügbare Ort, um Probleme zentral zu erfassen. Es ist im Allgemeinen der Ort, wo eine neue Gorouware hervorgebracht wurde (zB: per http accept). In einer ServeHTTP-Methode möchten Sie möglicherweise einzelne Paniken abfangen und protokollieren, ohne den Server neu zu starten (normalerweise sind solche Panics triviale Null-Derefs). Sie sehen möglicherweise Wiederherstellungen an Stellen, an denen Sie nicht nach einer Bedingung suchen können, die Sie wissen müssen - z. B. ob ein Dateihandle bereits geschlossen ist. (Schließen Sie einfach und behandeln Sie eine mögliche Panik).

Ich habe eine große Codebasis, die nur 2 oder 3 Mal verwendet. Sie sind nur für die genannten Fälle, und ich mache es nur, um sicherzustellen, dass das Problem speziell protokolliert wird. Ich würde eine Wiederherstellung durchführen, nur um die Nachricht zu protokollieren, selbst wenn ich noch zu os.Exit gehen würde und das Skript, das mich gestartet hat, mich neu starten.