En Go, el tipo struct{} representa una estructura sin campos y ocupa 0 bytes de memoria. Esta es una característica valiosa que se utiliza para minimizar el consumo de recursos en casos donde lo importante es la existencia de algo, pero no se necesitan datos, como por ejemplo, en la implementación de conjuntos (set), estructuras de señalización o canales para eventos.
Ejemplo de uso para conjunto:
mySet := make(map[string]struct{}) mySet["foo"] = struct{}{} if _, ok := mySet["foo"]; ok { fmt.Println("foo está presente en mySet") }
struct{} se utiliza como valor para mostrar la presencia de la clave.map[string]bool, la opción con struct{} ahorra más memoria.Canales de señalización:
done := make(chan struct{}) // La gorutina espera la señal de finalización <-done
¿Cuál es la diferencia entre map[string]struct{} y map[string]bool al implementar un conjunto? ¿Por qué es preferible map[string]struct{} y tiene desventajas?
Respuesta:
map[string]struct{} utiliza 0 bytes por valor, siendo la opción más compacta: se ahorra memoria, especialmente con grandes cantidades de datos.map[string]bool requiere 1 byte por valor (internamente puede ocupar más memoria debido a la alineación).map[string]struct{}: no se puede obtener rápidamente una lista de todos los valores marcados como true, si se necesita un valor booleano. Aún así, se requiere una iteración sobre las claves.Ejemplo:
set := make(map[string]struct{}) set["Alice"] = struct{}{} _, exists := set["Alice"] // true flags := make(map[string]bool) flags["Alice"] = true _, exists := flags["Alice"] // true
Historia
En un proyecto para almacenar identificadores únicos, se utilizó map[string]bool, lo que llevó a un aumento significativo en el consumo de memoria a medida que crecía la cantidad de datos: cientos de megabytes en comparación con la opción de map[string]struct{}. Cambiar a struct{} redujo el consumo de memoria en más de la mitad.
Historia
Un novato señalaba la finalización de la gorutina a través de
chan bool. Con un gran número de gorutinas, la transmisión de valores resultó ser excesiva: no se analizó si llegótrueofalse. Reemplazarlo porchan struct{}mostró una inexactitud arquitectónica y permitió simplificar el código.
Historia
En una biblioteca, se implementó un conjunto a través de map, donde como valor se usaba string. Esto ocupaba demasiada memoria. Después de una revisión de código, se cambió a map[tipo]struct{}. El error fue detectado tras analizar el perfil de memoria durante pruebas de carga, cuando la aplicación fallaba por OOM.