Geschiedenis van de kwestie:
Go onderscheidt zich van veel andere talen door de benadering van foutafhandeling, waarbij fouten waarden zijn en geen uitzonderingen. Dit ontwerp is gekozen omwille van transparantie en eenvoud: elke keer dat er iets mis kan gaan, retourneert de functie de fout expliciet als een tweede retourwaarde.
Probleem:
Veel beginners proberen de gebruikelijke patronen van try-catch op Go toe te passen, raken verdwaald in het grote aantal foutcontroles of maken geen gebruik van het inpakken van fouten om context door te geven. Dit leidt tot verlies van informatiewaarde en moeilijke debugging.
Oplossing:
In Go wordt een functie die een fout kan retourneren als volgt gedeclareerd:
func doSomething() (ResultType, error) { // ... if somethingWrong { return nil, errors.New("er is iets misgegaan") } return result, nil }
Foutcontrole is de verantwoordelijkheid van de aanroeper:
res, err := doSomething() if err != nil { log.Fatalf("proces mislukt: %w", err) }
Go 1.13 en hoger staan het "inpakken" van fouten toe met fmt.Errorf("%w", err) voor het opbouwen van foutketens. Dit verbetert de diagnose en bevordert de beste praktijk van contextuele beschrijving van fouten.
Belangrijke kenmerken:
Waarom eigen fouttypen maken als je gewoon errors.New("...") kunt retourneren?
Het juiste antwoord: eigen fouttypen stellen je in staat niet alleen de fouttekst door te geven, maar ook extra informatie op te slaan voor verdere verwerking (bijvoorbeeld retourcodes, context), en om meer verfijnde behandeling door type assertion mogelijk te maken.
Voorbeeld:
type NotFoundError struct { Resource string } func (e NotFoundError) Error() string { return fmt.Sprintf("%s niet gevonden", e.Resource) } // Controle if _, ok := err.(NotFoundError); ok { // verwerkingsfout voor zoeken }
Is panic een goede vervanging voor error voor kritieke fouten?
Nee, panic in Go wordt alleen gebruikt in werkelijk uitzichtloze situaties — bijvoorbeeld, bij fouten in de programmatuur (programminvarianten), maar niet voor gewone fouten (bijvoorbeeld, het openen van een bestand is mislukt). Het gebruik van panic om routinematige fouten aan te geven is verkeerd en leidt tot onleesbare, ongecontroleerde code.
Wat gebeurt er als je de foutafhandeling (err) in geneste functies overslaat?
De fout "verdwijnt", de code blijft uitgevoerd worden, wat kan leiden tot de verspreiding van een foutieve toestand. Het is altijd belangrijk om elke terugkeer van een fout correct te verwerken.
_ = ...Elke functie retourneert gewoon errors.New(...), fouten zijn niet ingepakt, fouttypen zijn verschillend, maar de verwerking is altijd hetzelfde — gelogd en weggegooid. Als gevolg hiervan zijn logbestanden vol met niet-informatieve berichten, die niet naar de oorspronkelijke oorzaak kunnen worden herleid.
Voordelen:
Nadelen:
Er worden fouten ingepakt via fmt.Errorf("%w", err), eigen fouten met nuttige velden, controles via errors.Is()/errors.As(). Hierdoor kan er met details worden gelogd, kunnen zakelijke fouten worden gescheiden van omgevingsfouten en kan er betrouwbare retry-logica worden geschreven.
Voordelen:
Nadelen: