Ένα παράδειγμα της διαρροής της γκουρού και πώς να εντοπίζετε ένα σφάλμα

Όταν έρχομαι σε μια λειτουργία που συνδυάζει την εκτέλεση ενός κομματιού κώδικα σε ένα γκουρού και την επικοινωνία / ακύρωση χρησιμοποιώντας κανάλια, είμαι συνήθως στον πειρασμό να κοιτάξουμε βαθύτερα, καθώς είναι ένα εξαιρετικό μέρος για να εισαγάγει μια διαρροή γκουρού εύκολα και τα λάθη αυτά είναι αρκετά εύκολο να χάσετε ακόμα και για μη αρχάριο golang προγραμματιστή. Και αυτό έκανα για αυτό το κομμάτι του κώδικα που βρήκα στο KUDO.

Τι είναι η διαρροή γκουρού;

Η διαρροή της γκουρού είναι βασικά ένας τύπος διαρροής μνήμης. Ξεκινάτε μια γκουρού, αλλά αυτό δεν θα τελειώσει ποτέ, καταλαμβάνοντας για πάντα μια μνήμη που έχει κρατήσει. Για να απλοποιήσω το παράδειγμα που δημοσίευσα λίγο από το KUDO, αυτό είναι ένα παράδειγμα για το πώς μπορεί κανείς να εισάγει μια διαρροή γκουατίνης στο έργο τους.

Αυτό που κάνει ο κώδικας είναι ότι υπάρχει ένα αναγκαστικό χρονικό όριο και μια περιοδική λειτουργία που τρέχει μέσα σε μια γκουρού. Κάθε τσιμπούρι, προσπαθούμε να επαληθεύσουμε κάποια επιχειρησιακή λογική (επιβεβαιώστε ότι κάτι είναι υγιές / έτοιμο για παράδειγμα) - σε αυτό το παράδειγμα απλά προσομοιώνει αυτή την κλήση ύπνου και στη συνέχεια επιστρέφει.

Έτσι πού είναι η διαρροή; Στο απλοποιημένο παράδειγμα παραπάνω, το χρονικό όριο είναι μόλις 1 δευτερόλεπτο, ενώ η διαδικασία επαλήθευσης διαρκεί 10 δευτερόλεπτα. Αυτό σημαίνει ότι η προθεσμία θα επιβληθεί πρώτα, επιστρέφοντας από το "waitReady". Περίπου 9 δευτερόλεπτα αργότερα, η gorutine μας λαμβάνει το αποτέλεσμα από τον επαληθευτή και προσπαθεί να γράψει στο doneChan. Η εγγραφή στο κανάλι χωρίς μνήμη εμποδίζει και κανείς δεν ακούει σε αυτό το κανάλι επειδή έχουμε ήδη επιστρέψει από το waitReady - και εδώ είναι η διαρροή μας!

Πώς να μάθετε αν έχετε διαρροή γκουρού;

Σε γενικές γραμμές, το πακέτο `runtime` είναι ο φίλος σας εδώ. Ένας τρόπος είναι η χρήση runtime.NumGoroutine () σε μια δοκιμή πριν και μετά την κλήση της λειτουργίας waitReady. Αν ο αριθμός των γκουρτρινών πριν από την αναμονή και μετά δεν είναι ο ίδιος, έχετε μια διαρροή.

Μια άλλη επιλογή είναι να χρησιμοποιήσετε μια βιβλιοθήκη από το Uber - goleak. Αν βυθίσετε πώς υλοποιείται αυτό, βασίζεται επίσης στο πακέτο χρόνου εκτέλεσης, αυτή τη φορά διαβάζει όλες τις στοίβες (λειτουργία runtime.Stack) και εισάγει μερικές μεθόδους ευκολίας πάνω από αυτό.