Achtergrond van de vraag:
Een goroutine-lek is een situatie waarin een goroutine blijft bestaan en in het geheugen hangt, terwijl het feitelijk "zinloos" is geworden (de berekening is voltooid, de gegevens zijn niet nodig, maar er is geen uitstapvoorwaarde). Dit is vergelijkbaar met geheugenlekken, maar dan voor uitvoeringsdraadjes. Dit is kritisch voor Go — een hoge belasting kan leiden tot uitputting van middelen.
Probleem:
In tegenstelling tot andere talen, waar directe beheersing van draadjes vaak leidt tot handmatig sluiten, worden goroutines in Go eenvoudig gestart, maar worden ze niet altijd correct beëindigd. Een veelvoorkomende fout: de primaire logica is voltooid, maar de goroutine is "bevroren" — wacht op gegevens van een gesloten kanaal of wacht in het geheel niet op een signaal.
Oplossing:
Om lekken te voorkomen, worden controleconstructies gebruikt: context, het sluiten van kanalen, signaalvariabelen. Het is belangrijk om van tevoren de uitstaproutes uit elke goroutine te ontwerpen en defer te gebruiken voor opschoning. Voorbeeld:
func worker(ctx context.Context, jobs <-chan int, results chan<- int) { for { select { case <-ctx.Done(): return case job, ok := <-jobs: if !ok { return } results <- job * 2 } } }
Belangrijkste kenmerken:
Kun je gewoon een kanaal sluiten om de goroutine te stoppen?
Niet altijd. Als er andere case in de select zijn, of er is geen controle op sluiting via ok, kan de goroutine blijven "hangen".
val, ok := <-ch if !ok { return } // Dit is correcter
Wat gebeurt er als je vergeet context.Done in de select te verwerken?
De goroutine zal nooit weten dat de annulering heeft plaatsgevonden — deze blijft "eeuwig" hangen. Dit is de directe weg naar een lek.
Kun je een lek detecteren met behulp van go runtime?
Er is geen standaardhulpmiddel voor het volgen van lekken. Je moet het aantal actieve goroutines monitoren via runtime.NumGoroutine of een lekdetecteerder van derden gebruiken.
In een push-verzendingssysteem worden goroutines gestart voor elk binnenkomend bericht, maar ze vergeten ze te stoppen bij annulering van de context of sluiting van het kanaal — honderden "dode" goroutines hangen in het geheugen.
Voordelen:
Nadelen:
Het werk van goroutines wordt gecontroleerd via context, op het niveau van de bedrijfslogica wordt de uitstap uit de select gecontroleerd, na succesvolle verzending/verwerking wordt het kanaal gesloten.
Voordelen:
Nadelen: