Las estructuras map y slice en Go tienen características importantes de copia y semántica de trabajo con la memoria, que a menudo conducen a comportamientos inesperados en desarrolladores inexpertos.
Aunque Go se considera un lenguaje estricto con tipado estático y sin punteros por defecto, tanto map como slice implementan un modelo interno especial: ambos tipos son estructuras de referencia. Esto impone limitaciones y crea numerosos matices al copiar y pasar estos objetos.
La copia de map y slice no conduce a una copia profunda del contenido, sino que forma una nueva referencia al mismo objeto, lo que provoca efectos secundarios inesperados al modificar datos, devolver valores incorrectos de funciones y realizar modificaciones. Además, devolver map o slice como resultado de una función puede causar asignaciones adicionales o fugas.
b := a[:]). Para copiar completamente los elementos, se debe utilizar la función incorporada copy().Ejemplo de copia correcta:
// Copiando un slice a := []int{1, 2, 3} b := make([]int, len(a)) copy(b, a) // b ahora es independiente de a // Copiando un map src := map[string]int{"x": 1} dst := make(map[string]int) for k, v := range src { dst[k] = v }
Características clave:
slice y map son tipos de referencia, se copian por descriptor, no por contenido¿Qué sucederá si simplemente asigno un map/slice a otro y luego cambio uno de ellos?
Tanto el map como el slice apuntarán a los mismos datos en memoria: el cambio afectará a ambos objetos.
¿Por qué al devolver slice o map de una función se dice a menudo "es eficiente en memoria"?
Porque se devuelve una copia del descriptor, no de todo el contenido, los datos en el montón viven mientras haya referencias a ellos.
¿Se puede usar la función copy() para hacer una copia "profunda" de un map?
No, copy() solo funciona con slices y arreglos, para maps siempre se necesita un ciclo.
Un desarrollador copia un slice o un map mediante asignación y cambia la copia para protegerse de efectos secundarios:
Ventajas:
Desventajas:
Antes de modificar los datos necesarios, se usa copy() para slice y un ciclo para map:
Ventajas:
Desventajas: