Sobes.tech
Middle

Γιατί δεν μπορούμε να πάρουμε την αναφορά στην τιμή που αποθηκεύεται με κλειδί σε έναν χάρτη;

sobes.tech AI

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

Στο Golang, ένα map αντιπροσωπεύει έναν πίνακα κατακερματισμού. Η προσθήκη ή η διαγραφή στοιχείων μπορεί να οδηγήσει σε αλλαγές στη εσωτερική δομή του map, συμπεριλαμβανομένης της επανακατανομής μνήμης και της μετακίνησης στοιχείων. Αν πάρεις έναν δείκτη στην τιμή που αποθηκεύεται με το κλειδί και στη συνέχεια αλλάξεις το map (π.χ., προσθέτοντας ή διαγράφοντας άλλο στοιχείο), αυτός ο δείκτης μπορεί να γίνει άκυρος, δείχνοντας σε λανθασμένη περιοχή μνήμης ή σε άλλη τιμή. Το Golang αποτρέπει αυτό κατά τη φάση της μεταγλώττισης, απαγορεύοντας το να πάρεις τη διεύθυνση ενός στοιχείου του map.

Επιπλέον, το map στο Golang δεν είναι ασφαλές για πολλαπλά νήματα (thread-safe). Η άμεση αλλαγή της τιμής μέσω δείκτη θα μπορούσε να οδηγήσει σε συνθήκες αγώνα αν διαφορετικές goroutines έχουν πρόσβαση ταυτόχρονα, καθιστώντας πιο δύσκολη τη συγχρονισμό. Ο περιορισμός στο να πάρεις δείκτη σε μια τιμή του map απλοποιεί το μοντέλο ταυτόχρονου πρόσβασης και καθιστά σαφή την ανάγκη χρήσης μηχανισμών συγχρονισμού (π.χ., sync.RWMutex) κατά την εργασία με maps σε περιβάλλοντα πολλαπλών νημάτων.

Για να αλλάξεις την τιμή με βάση το κλειδί, πρέπει να πάρεις την τιμή, να την αλλάξεις και στη συνέχεια να την αποθηκεύσεις ξανά στο map:

package main

import "fmt"

func main() {
	m := map[string]int{"a": 1}

	// Δεν επιτρέπεται να πάρεις δείκτη στην τιμή του map
	// ptr := &m["a"] // Σφάλμα μεταγλώττισης

	// Ο σωστός τρόπος να αλλάξεις την τιμή:
	value := m["a"] // Πάρε την τιμή
	value++         // Άλλαξέ την
	m["a"] = value  // Αποθήκευσέ την ξανά

	fmt.Println(m["a"]) // Θα εμφανίσει 2
}