En Go, los mapas (map) no son seguros para hilos de forma predeterminada. Si varias goroutines escriben o leen simultáneamente de un mismo mapa sin sincronización, se producirá una condición de carrera (data race), lo que lleva a la pánico fatal error: concurrent map read and map write o a la corrupción de datos.
Para trabajar de forma segura con mapas, es necesario:
sync.Map, que está diseñado para escenarios concurrentes de alta carga.var mu sync.RWMutex m := make(map[string]int) // Escritura mu.Lock() m["key"] = 1 mu.Unlock() // Lectura mu.RLock() v := m["key"] mu.RUnlock() // O sync.Map var sm sync.Map sm.Store("key", 1) v, _ := sm.Load("key")
¿Por qué leer y escribir simultáneamente desde diferentes goroutines en un mapa en Go es tan peligroso si el mapa es un tipo incorporado?
Respuesta: En Go, el tipo incorporado mapa no proporciona sincronización. El acceso concurrente al mapa desde varias goroutines no solo produce valores incorrectos, sino que puede llevar a un fallo del programa. Incluso la lectura y escritura simultáneas (¡cuando no hay claves en conflicto!) pueden provocar un error fatal. Esto se diferencia de algunos otros lenguajes, en los que las colecciones son "tolerantes" a los accesos concurrentes.
Historia
En un proyecto real, un desarrollador utilizó un mapa global para almacenar en caché datos. El servicio funcionaba de manera estable en pruebas, pero durante las pruebas de carga y en producción comenzó a fallar con el error fatal error: concurrent map read and map write. La causa fue el acceso paralelo al mapa desde diferentes solicitudes http sin utilizar Mutex.
Historia
En una aplicación web Go, un programador decidió mejorar el rendimiento y utilizó un mapa normal como pool de conexiones, suponiendo que el marco de trabajo proporcionaba la multitarea. Con un aumento brusco del tráfico, el servicio comenzó a fallar sin una razón aparente: debido a la carrera, los datos en el mapa se corrompían y surgían pánicos.
Historia
En un servicio interno de Go, la aplicación utilizaba un mapa para recopilar estadísticas "sobre la marcha", pensando que el acceso principal era solo de escritura. De hecho, otra parte del código solicitaba periódicamente datos para generar informes, lo que conducía a caídas difíciles de detectar solo una vez al día, justo cuando se generaban las estadísticas. El análisis mostró que las lecturas y escrituras se cruzaban sin ninguna bloqueo.