2014-03-31 5 views
11

Ich möchte identifizieren, welche Art von Fehler in der Netzwerkebene aufgetreten ist. Der einzige Weg, den ich gefunden habe, war die Fehlermeldungen mit einem regulären Ausdruck zu überprüfen, aber jetzt habe ich entdeckt, dass diese Nachrichten in verschiedenen Sprachen (abhängig von der Betriebssystemkonfiguration) sein können, was es schwierig macht, sie mit regulären Ausdrücken zu erkennen. Gibt es einen besseren Weg, es zu tun?Portable Möglichkeit, verschiedene Arten von Netzwerkfehlern in Golang zu erkennen

package main 

import (
    "github.com/miekg/dns" 
    "net" 
    "regexp" 
) 

func main() { 
    var c dns.Client 
    m := new(dns.Msg) 

    m.SetQuestion("3com.br.", dns.TypeSOA) 
    _, _, err := c.Exchange(m, "ns1.3com.com.:53") 
    checkErr(err) 

    m.SetQuestion("example.com.", dns.TypeSOA) 
    _, _, err = c.Exchange(m, "idontexist.br.:53") 
    checkErr(err) 

    m.SetQuestion("acasadocartaocuritiba.blog.br.", dns.TypeSOA) 
    _, _, err = c.Exchange(m, "ns7.storedns22.in.:53") 
    checkErr(err) 
} 

func checkErr(err error) { 
    if err == nil { 
    println("Ok") 
    } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { 
    println("Timeout") 
    } else if match, _ := regexp.MatchString(".*lookup.*", err.Error()); match { 
    println("Unknown host") 
    } else if match, _ := regexp.MatchString(".*connection refused.*", err.Error()); match { 
    println("Connection refused") 
    } else { 
    println("Other error") 
    } 
} 

Ergebnis:

$ go run neterrors.go 
Timeout 
Unknown host 
Connection refused 

entdecken ich das Problem, wenn das System in einem Windows-Betriebssystem mit Portugiesisch als Standardsprache zu testen.

[EDIT]

fand ich einen Weg, es zu tun, um die OpError verwenden. Hier ist die checkErr-Funktion wieder mit dem neuen Ansatz. Wenn jemand eine bessere Lösung hat, werde ich sehr froh sein, es zu kennen!

func checkErr(err error) { 
    if err == nil { 
    println("Ok") 
    } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { 
    println("Timeout") 
    } else if opError, ok := err.(*net.OpError); ok { 
    if opError.Op == "dial" { 
     println("Unknown host") 
    } else if opError.Op == "read" { 
     println("Connection refused") 
    } 
    } 
} 

[EDIT 2]

nach seong Antwort aktualisiert.

func checkErr(err error) { 
    if err == nil { 
    println("Ok") 
    return 

    } else if netError, ok := err.(net.Error); ok && netError.Timeout() { 
    println("Timeout") 
    return 
    } 

    switch t := err.(type) { 
    case *net.OpError: 
    if t.Op == "dial" { 
     println("Unknown host") 
    } else if t.Op == "read" { 
     println("Connection refused") 
    } 

    case syscall.Errno: 
    if t == syscall.ECONNREFUSED { 
     println("Connection refused") 
    } 
    } 
} 
+4

go1.6 gibt '* os.SyscallError' anstelle von' syscall.Errno' zurück –

Antwort

2

Das Paket net arbeitet eng mit Ihrem Betriebssystem zusammen. Bei Betriebssystemfehlern verwendet die Go std-Bibliothek den pkg syscall. Schauen Sie hier: http://golang.org/pkg/syscall/

Das net Paket kann auch syscall.Errno Typ Fehler zurückgeben.

Für einen einfacheren Code in Ihrer checkErr Funktion könnten Sie einen Typenschalter verwenden (http://golang.org/doc/effective_go.html#type_switch).

+0

Das Go 'syscall'-Paket ist nicht portierbar; es hängt vom Betriebssystem ab. Das Go'os-Paket ist vom Betriebssystem unabhängig. ["Package syscall enthält eine Schnittstelle zu den Low-Level-Betriebssystem-Primitiven. Die Details hängen vom zugrunde liegenden System ab"] (http://golang.org/pkg/syscall/) – peterSO

+0

Woops, du hast absolut recht. Ich habe mir das falsche Pkg angesehen. – seong

+1

Ich habe die Antwort entsprechend geändert. Das 'net'-Paket kann' syscall.Ernno'-Fehler zurückgeben, aber die Details werden in der Tat abhängig von Ihrem Betriebssystem variieren. – seong

Verwandte Themen