2015-08-02 4 views
5

Der Typ error in Go ist ziemlich breit, und der tatsächliche Typ kann je nach Plattform und Version variieren. Ist es idiomatisch, Fehler zu filtern, die wir durch den String-Wert des Fehlers error.Error() erwarten?Idiomatisches Filtern von Fehlern in Go

Zum Beispiel:

_, err := conn.Write(b) 
if err != nil { 
    if !strings.Contains(err.Error(), "peer reset") { 
     log.Print(err) 
    } 
    return 
} 

Gibt es einen besseren Weg, dies zu tun?

+0

Stochern in der String-Darstellung von "Fehler" ist im besten Fall fragil und keine gute Idee. Ich schrieb [eine Antwort] (http://stackoverflow.com/a/30178766/55504) auf eine andere Frage, die aufzeigt, wie ein Paketautor Fehler machen kann, die von Konsumenten testbar sind. Wenn Sie Fehler, die keine dieser einfachen Methoden verwenden, testen oder behandeln müssen, haben Sie einen Fehler in diesem Paket gefunden und sollten es als Problem melden. Ich würde so weit gehen, es in einer Gabel zu fixieren, bevor ich mit der Fehlerstrecke herumgespielt hätte. –

+0

Ihr neues "stringly-typed" SO-Tag macht für mich keinen Sinn; Ich würde empfehlen, es zu entfernen. –

Antwort

1

Ich bin mir nicht sicher, dass ich etwas sage, was Sie nicht wissen, aber ich habe ein paar Möglichkeiten gesehen, mit bekannten Instanzen zu vergleichen, wenn sie exportiert werden und im Godoc erscheinen, wie io.EOF oder os.ErrNotExist ; Verwenden von type assertions oder switches, wenn die Dokumente einen Fehler eines bestimmten Typs versprechen, wie *os.PathError oder *os.LinkError; oder aufgeben und Nachrichten anschauen. Das erste sollte klar genug sein und du hast das dritte in deiner Frage getan; für Typ-Überprüfung könnte wie folgt aussehen:

if pathErr, ok := err.(*os.PathError); ok { 
    log.Fatal("Bad path " + pathErr.Path + ", giving up") 
} else if err != nil { 
    return err 
} 

ich denke, das selten sein würde, aber wenn man mehrere mögliche Arten beteiligt hatten, könnten Sie möglicherweise ein type switch verwenden:

switch err.(type) { 
case *os.PathError, *os.LinkError: 
    log.Fatal("oof") 
case nil: 
    // nothing; prevents default 
default: 
    log.Fatal("huh") 
} 

(Die Wahl des Irrtums und Verhalten hier ist ein bisschen albern - ich versuche nur, eine Vorlage mit der Syntax aufzustellen.)

Der schwierige Teil, auf den Sie in Ihrer Frage anspielen: es ist vielleicht nicht klar, was Sie über was Fehler garantieren zurück. Ich weiß, dass zum Beispiel die 1.5 release notes sagen, dass sie mehr auf net.OpError für Netto-Fehler als zuvor standardisieren, aber das ist alles, was ich weiß. Wenn Sie in der Quelle des Pakets, das Sie angerufen haben, spekulieren oder Fragen stellen, kann das in Ordnung sein, wenn es wichtige Fälle gibt, von denen Sie denken, dass sie unklar sind.

+1

Sie haben ziemlich genau zusammengefasst, wo ich gerade bin. –

+0

Ihr Beispiel ist Netto-Fehler; frage mich, ob es sich lohnt, golang-nuts über das Hinzufügen eines '(* net.OpError) .Type()' zu fragen, wobei 'Type' einer der bekannten Fehlerwerte ist (imagine, net.ErrConnReset',' net.ErrAddrInUse') usw.) - oder um 'opError.Error()' zu standardisieren oder zu dokumentieren, ob einige Dinge tatsächlich zuverlässig, aber nicht dokumentiert sind. – twotwotwo

+0

(Wenn nicht 'Type()', vielleicht ein 'Code()' oder 'Errno()' mit POSIX-Fehlercodes.) – twotwotwo