programowanieProgramista Backend

Opowiedz, jak Go implementuje zarządzanie pamięcią podczas przekazywania map i slice do funkcji i jakie mogą być tego konsekwencje?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W Go struktura map zawsze jest przekazywana przez wartość, ale ta wartość zawiera wskaźnik do wewnętrznych struktur samej map (pod maską – tabela haszowa). Dlatego jeśli przekazujesz map do funkcji i wewnątrz funkcji zmieniasz zawartość (dodajesz/usuwasz elementy), zmiany będą widoczne na zewnątrz. Podobnie zachowują się slice – kopiowana jest struktura slice, ale nie sama tablica-dane: slice zawiera wskaźnik do tablicy, długość i pojemność. Jeśli zmieniasz wartości po indeksie wewnątrz funkcji, pierwotna tablica również ulegnie zmianie. Ale jeśli z funkcji przypisujesz nowy slice (na przykład, reslice), pierwotna zmienna się nie zmieni.

func updateMap(m map[string]int) { m["key"] = 42 // Zmiany są widoczne na zewnątrz! } func updateSlice(s []int) { s[0] = 99 // Zmienia się pierwotna tablica }

Pytanie z pułapką.

Dlaczego przy przekazywaniu map i slice do funkcji ich zmiany wewnątrz funkcji odzwierciedlają się na "oryginale"?

Odpowiedź: Ponieważ kopiowana jest tylko struktura wskaźnika, a same dane pozostają wspólne – wszelkie zmiany dotyczą tego samego bloku pamięci.

Przykłady rzeczywistych błędów z powodu braku znajomości subtelności tematu.


Historia

W projekcie fintech przekazywano map z ustawieniami konfiguracyjnymi do różnych serwisów, zakładając, że lokalne zmiany nie wpłyną na ogólny map. W rezultacie jeden serwis zmienił wartości, co spowodowało błędy w innych modułach, które otrzymały niespodziewanie zmienioną konfigurację.


Historia

W mikroserwisie analitycznym przekazywano slice, zakładając, że otrzymają niezależne kopie. Ale funkcja wewnątrz zmieniła wartości po indeksie, co doprowadziło do zniekształconych danych w raporcie, ponieważ pierwotna tablica została niespodziewanie zmieniona.


Historia

Na serwerach gier używano map do przechowywania sesji użytkowników i jednocześnie przekazywano tę map do kilku gorutyn. Zakładano, że każda gorutyna pracuje z swoją kopią, ale faktycznie doszło do wyścigu danych i częściowego utracenia sesji.