ProgrammatieBackend Go ontwikkelaar

Hoe werkt het ingebouwde package context in Go? Waarvoor wordt het gebruikt, hoe maak je contexten correct aan en beëindig je ze? Welke fouten worden vaak gemaakt bij het gebruik ervan?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Het package context is de standaard voor het beheren van de levensduur (annulering, time-out) en het doorgeven van metadata tussen delen van de code, vooral bij het werken met goroutines en externe oproepen (HTTP, DB).

Creëren:

  • context.Background() — de root context
  • context.WithCancel(parent) — nieuw met annulering
  • context.WithTimeout(parent, duration) — met time-out
  • context.WithValue(parent, key, value) — met gegevens

Het is belangrijk om de context te beëindigen voor de juiste vrijgave van middelen. Voorbeeld:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() // daarna wordt ctx gebruikt in goroutine/HTTP-aanroep

Typisch patroon — geef context als eerste argument aan functies, voorbeeld:

func process(ctx context.Context) error { ... }

Vraag met een haakje

Wanneer kun je context.TODO() en context.Background() doorgeven in plaats van de echte context, en wat is het verschil tussen hen?

Veel mensen gebruiken context.Background() als placeholder. Maar:

  • context.Background() — wortel van de boom, gebruik alleen in main() en tests, bij de initialisatie van de "contextboom" zelf.
  • context.TODO() is nodig als het nog niet duidelijk is welke context nodig is — voor tijdelijke "oplossingen" tijdens refactoring. In productiecoded is TODO onaanvaardbaar: je moet precies weten wat en waarover wordt doorgegeven.

Voorbeelden van echte fouten door onwetendheid van de subtiliteiten van het onderwerp


Verhaal

In de microservice vergaten ze cancel() aan te roepen na het aanmaken van context.WithTimeout() — aanvragen kwamen vast te zitten, beëindigde goroutines lieten "hangende" timers achter in de runtime, wat leidde tot geheugenlekken.


Verhaal

Door context.Background() door te geven in plaats van de context die uit de aanvraag kwam in handlers, werd de hele keten van annulering en trace-id verloren, waardoor time-outbeperkingen niet werkten en annuleringen van aanvragen niet plaatsvonden.


Verhaal

Via context.WithValue() gaven ontwikkelaars gegevens door, maar de sleutels waren strings. Als gevolg hiervan, door mogelijke sleutelconflicten uit verschillende pakketten, ontstonden onverwachte fouten ("sleutel is al bezet"). Goede praktijk: gebruik unieke types voor sleutels.