2015-08-02 11 views
5

Il tipo error in Go è piuttosto ampio e il tipo effettivo contenuto può variare a seconda della piattaforma e delle versioni. È idiologico filtrare gli errori che ci aspettiamo dal valore stringa dell'errore, error.Error()?Errori di filtraggio idioomatici in Go

Ad esempio:

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

C'è un modo migliore per fare questo?

+0

Poking in giro nella rappresentazione di stringa di 'error' è fragile al meglio e non è una buona idea. Ho scritto [una risposta] (http://stackoverflow.com/a/30178766/55504) a un'altra domanda che riguarda i modi in cui un autore di pacchetti può commettere errori verificabili dai consumatori. Se hai bisogno di testare o gestire errori che non usano uno di quei metodi facili, allora hai trovato un difetto in quel pacchetto e dovresti segnalarlo come un problema. Mi spingerei fino al punto di fissarlo in una forchetta, prima di passare inosservato con la stringa dell'errore. –

+0

Il tuo nuovo tag SO "tipizzato rigorosamente" non ha senso per me; Consiglierei di rimuoverlo. –

risposta

1

Non sono sicuro di dire qualcosa che non si conosce, ma ho visto alcuni modi per gestirlo: confrontare le istanze conosciute quando vengono esportate e compaiono nel godoc, come io.EOF o os.ErrNotExist ; utilizzando le asserzioni o gli switch di tipo quando i documenti promettono un errore di un certo tipo, come *os.PathError o *os.LinkError; o rinunciare e guardare i messaggi. Il primo dovrebbe essere abbastanza chiaro e hai fatto il terzo nella tua domanda; il controllo di tipo potrebbe essere simile:

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

Penso che questo sarebbe rara, ma se si ha diversi tipi potenziali coinvolti, si potrebbe in teoria usare un type switch:

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

(La scelta di errore e di il comportamento qui è un po 'sciocco - sto solo provando a mettere un modello con la sintassi.)

La parte difficile a cui alludi nella tua domanda: potrebbe non essere chiaro cosa garantisce di avere su quali errori saranno essere restituito So che, ad esempio, il 1.5 release notes dice che sta standardizzando di più su net.OpError per errori netti di prima, ma questo è tutto ciò che so. Speleggiare nell'origine del pacchetto che stai chiamando o porre domande alle persone potrebbe essere utile se ci sono casi importanti che ritieni non chiari.

+1

Hai riassunto più o meno dove sono attualmente. –

+0

Il tuo esempio è errori netti; mi chiedo se valga la pena di chiedere a golang-nuts di aggiungere un '(* net.OpError) .Type()' dove 'Type' è uno di un insieme di valori di errore noti (imagine,' net.ErrConnReset', 'net.ErrAddrInUse' , ecc.) - o per standardizzare 'opError.Error()', o per documentare se alcune cose sono effettivamente affidabili ma non documentate. – twotwotwo

+0

(Se non 'Type()', forse un 'Code()' o 'Errno()' usando i codici di errore POSIX.) – twotwotwo