Eliminando una clave de un map en Go: ¿qué se esconde bajo el capó?

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Delete key in map: cómo funciona bajo el capó en Go

\n\n

¿Alguna vez te has preguntado qué sucede realmente cuando escribes delete(myMap, "key") en Go? ¿La clave simplemente desaparece de la memoria? ¿O queda un "hueco"? ¿Y qué pasa si eliminas una clave de un map nil? Si te has hecho estas preguntas, no estás solo. El tema de delete key in map ha acumulado miles de visitas en Stack Overflow, y hoy vamos a mirar bajo el capó de esta acción aparentemente simple.

\n\n

En este artículo SEO, analizaremos cómo está estructurada la tabla hash en Go (estructura hmap), cómo funciona la eliminación de una clave, dónde va la memoria y por qué no debes temer a delete en los bucles. ¡Allá vamos!

\n\n

Breve introducción: cómo está estructurado el map en Go

\n\n

Antes de hablar sobre la eliminación, recordemos cómo map golang almacena datos. Internamente, es una tabla hash, la estructura hmap. Consiste en un array de "cubos" (buckets), cada uno de los cuales puede almacenar hasta 8 pares clave-valor. Cuando agregas una clave, Go calcula el hash, encuentra el cubo y coloca el par dentro. Si el cubo se desborda, se crea una cadena de desbordamiento (overflow bucket).

\n\n

Esta es una implementación clásica, pero con un par de trucos de los que hablaremos a continuación.

\n\n

Estructura de hmap (simplificada)

\n\n
type hmap struct {\n    count     int     // número de elementos\n    flags     uint8\n    B         uint8   // logaritmo del número de cubos\n    buckets   unsafe.Pointer // puntero al array de cubos\n    oldbuckets unsafe.Pointer // durante el crecimiento del map\n    nevacuate uintptr\n    // ...\n}
\n\n

Clave: buckets es un array continuo. La eliminación no comprime este array, solo marca la celda como "vacía".

\n\n

Delete key in map: cómo funciona a nivel de código

\n\n

La llamada delete(m, k) en Go es una función incorporada que se compila en una llamada al runtime. Internamente, ocurre aproximadamente lo siguiente:

\n\n
    \n
  1. Cálculo del hash de la clave — Go utiliza una función hash específica para el tipo de clave.
  2. \n
  3. Búsqueda del cubo — los bits menos significativos del hash determinan el número del cubo.
  4. \n
  5. Búsqueda lineal dentro del cubo (y las cadenas de desbordamiento) — encuentra la celda con la clave deseada.
  6. \n
  7. Limpieza de memoria — Go pone a cero la memoria de la clave y el valor para que el recolector de basura pueda recogerlos.
  8. \n
  9. Marcado de la celda como "vacía" — con una bandera especial emptyRest o emptyOne.
  10. \n
  11. Reducción del contador — m.count--.
  12. \n
\n\n

Todo esto ocurre en O(1) en promedio, pero teniendo en cuenta las colisiones, puede ser O(n) en el peor de los casos.

\n\n

Ejemplo de código: delete en acción

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    m := map[string]int{\n        "apple":  5,\n        "banana": 3,\n        "cherry": 7,\n    }\n\n    fmt.Println("Antes de eliminar:", m)\n    delete(m, "banana")\n    fmt.Println("Después de eliminar:", m)\n\n    // Intentemos eliminar una clave inexistente\n    delete(m, "grape") // no ocurre nada, no hay error\n    fmt.Println("Después de eliminar una inexistente:", m)\n}
\n\n

Ten en cuenta: delete key in map para una clave inexistente es una operación segura. Simplemente no hace nada. Este es uno de los errores comunes entre los principiantes.

\n\n

¿Qué sucede con la memoria? Mitos y realidad

\n\n

Muchos desarrolladores temen que después de delete queden "huecos" en el map que provoquen fugas de memoria. Vamos a aclararlo.

\n\n

Memoria para claves y valores

\n\n

Cuando eliminas una clave, Go pone a cero la memoria de ese elemento. Si la clave o el valor eran punteros o contenían punteros (strings, slices, maps), el recolector de basura podrá recogerlos. La celda en sí en el cubo permanece, pero está marcada como vacía.

\n\n

Esto significa que el map no se reduce de tamaño en

Blogs

Book Recommendations