Las estructuras en Go se copian por valor (copia profunda de primer nivel, las estructuras anidadas se copian según la misma regla), mientras que los slices se copian por valor, pero solo se copia la estructura, no el array de datos subyacente: tanto el original como la copia del slice apuntan al mismo array de respaldo, por lo que un cambio a través de un slice se reflejará en el otro, a menos que se haga una copia explícita del array mediante copy().
Ejemplo de copia de un slice:
s1 := []int{1,2,3} s2 := s1 // ¡punteros al mismo buffer! s2[0] = 99 fmt.Println(s1) // [99 2 3] // Para copiar el array: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 es independiente
Al copiar estructuras: si la estructura contiene un campo puntero o un campo slice, solo se copian las referencias y no los valores.
¿Cuál es la forma de "clonar" un slice para que sus cambios no afecten al original?
Respuesta potencialmente errónea: Simplemente hacer b := a. Correcto:
copy, crear un nuevo slice de la longitud necesaria y copiar los datos:newS := make([]int, len(a)) copy(newS, a)
Historia
Descripción: Al generar consultas a la base de datos, se cambiaban dinámicamente los campos del slice en la estructura de la consulta sin hacer copias. En solicitudes repetidas, los datos se cruzaban, dando resultados incorrectos para los usuarios.
Historia
Descripción: Al procesar datos en paralelo, se creaba una copia de la estructura mediante asignación y se ampliaba el slice en una gorutina, utilizando simultáneamente otro slice original. Los datos "se sobreescribían", lo que llevaba a errores impredecibles.
Historia
Descripción: Se utilizó una estructura de buffer, la copia simultánea mediante asignación no tenía en cuenta los slices anidados (copia superficial), los cambios en un lugar afectaban a otro buffer, lo que dificultaba rastrear la fuente de los cambios en los datos.