Sobes.tech
Middle

Πώς λειτουργεί το Map στο Go;

sobes.tech AI

Απάντηση από AI

Ο χάρτης σε Go υλοποιείται ως πίνακας κατακερματισμού.

Τα βασικά στοιχεία της δομής map:

  • Λειτουργία κατακερματισμού: Χαρτογραφεί τα κλειδιά σε τιμές κατακερματισμού (ακέραιοι αριθμοί).
  • Πίνακας κάδων (buckets): Συλλογή από λίστες ή πίνακες όπου αποθηκεύονται τα ζεύγη κλειδιού-τιμής. Ο δείκτης του κάδου καθορίζεται από την τιμή κατακερματισμού του κλειδιού.
  • Διαχείριση συγκρούσεων: Όταν διαφορετικά κλειδιά έχουν τον ίδιο κατακερματισμό (σύγκρουση), τα στοιχεία με αυτά τα κλειδιά αποθηκεύονται στον ίδιο κάδο, συνήθως με μορφή συνδεδεμένης λίστας ή κάδου υπερχείλισης.
  • Παράγοντας φόρτωσης: Αναλογία μεταξύ του αριθμού των στοιχείων και του αριθμού των κάδων. Όταν ξεπεραστεί ένα όριο, πραγματοποιείται επανακατακερματισμός: δημιουργείται ένας νέος μεγαλύτερος πίνακας κάδων και μετακινούνται όλα τα στοιχεία από τους παλιούς κάδους στους νέους.

Η δομή map σε Go αντιπροσωπεύεται από τον τύπο hmap:

 type hmap struct {
    count     int // Αριθμός στοιχείων
    flags     uint8 // Σημαίες κατάστασης
    B         uint8 // log_2 του αριθμού των κάδων (αριθμός κάδων είναι 2^B)
    noverflow uint16 // Αριθμός κάδων με υπερχείλιση (μόνο για στατιστικά)
    hash0     uint32 // Αρχική τιμή της λειτουργίας κατακερματισμού

    buckets    unsafe.Pointer // Δείκτης στον πίνακα κάδων (κύριοι και υπερχείλισης)
    oldbuckets unsafe.Pointer // Δείκτης στον παλιό πίνακα κάδων κατά τη διάρκεια μετανάστευσης
    nevacuate  uintptr // Δείχνει μέχρι ποιον παλιό κάδο έχει ολοκληρωθεί η μετανάστευση

    extra *mapextra // Επιπλέον πληροφορίες (προαιρετικό)
}

 type mapextra struct {
    overflow    *[2]*[]*bmap // Δείκτες σε πίνακες υπερχείλισης
    oldoverflow *[2]*[]*bmap // Δείκτες σε παλιούς πίνακες υπερχείλισης
    nextOverflow *bmap // Επόμενος ελεύθερος κάδος υπερχείλισης
}

 type bmap struct {
    tophash [8]uint8 // Top hash (ανώτερα bits του hash) για επιτάχυνση της αναζήτησης στον κάδο
    // Ακολουθούν κλειδιά, τιμές και δείκτες στον επόμενο bmap (αν ο κάδος είναι υπερχείλισης)
    // Διανείμετε όλα τα δεδομένα για το hmap.buckets σε ένα ενιαίο malloc μπλοκ
    // δείτε ../../runtime/map.go για λεπτομέρειες
}

Ενέργειες:

  • Εισαγωγή/Ενημέρωση: Υπολογίζεται το hash του κλειδιού, καθορίζεται ο κάδος. Αν το κλειδί ήδη υπάρχει, ενημερώνεται η τιμή. Αλλιώς, το ζεύγος κλειδιού-τιμής προστίθεται στον κάδο. Σε περίπτωση υπερχείλισης ή υπέρβασης του Load Factor, μπορεί να πραγματοποιηθεί rehashing.
  • Αναζήτηση: Υπολογίζεται το hash του κλειδιού, καθορίζεται ο κάδος. Τα στοιχεία στον κάδο ελέγχονται με βάση το top-hash, και στη συνέχεια συγκρίνονται τα πλήρη κλειδιά. Επιστρέφεται η τιμή και ένα flag ύπαρξης.
  • Διαγραφή: Υπολογίζεται το hash του κλειδιού, καθορίζεται ο κάδος. Το στοιχείο σημαίνεται ως διαγραμμένο (αλλά δεν διαγράφεται άμεσα από τη μνήμη). Η διαγραφή πραγματοποιείται σε μελλοντικές ενέργειες ή κατά το rehashing.

Ο χάρτης σε Go δεν είναι συγχρονισμένος και δεν μπορεί να χρησιμοποιηθεί με ασφάλεια από πολλαπλές goroutines χωρίς εξωτερικό συγχρονισμό.