Arrays vs Slices en Go: Difference Crítica que Debes Conocer
Introducción
¿Alguna vez te has preguntado por qué un []int en Go se comporta de forma diferente a un [5]int? Si trabajas con Go, entender las diferencias entre arrays y slices es clave para escribir código eficiente y evitar errores sutiles. En este artículo, desglosaremos de forma práctica las conceptos como capacity, len y aliasing, mostrando ejemplos con su salida esperada.
Este contenido está dirigido a desarrolladores que ya tienen bases en Go pero quieren dominar estructuras de datos como arrays y slices. Al finalizar, sabrás cuándo usar cada una y cómo evitar trampas comunes.
¿Qué son los Arrays en Go?
Un array en Go es una estructura fija con un tamaño definido en tiempo de compilación. Por ejemplo:
arr := [5]int{1, 2, 3, 4, 5}
fmt.Println(len(arr)) // Salida: 5Aquí, len(arr) devuelve 5, que es el número de elementos. Como los arrays son fijos, su capacity (tamaño de la memoria reservada) también es 5.
Características clave:
- Tamaño inmutable en tiempo de ejecución.
- almacenamiento garantizado en memoria continua.
- Copia directa al asignar variables.
¿Qué son los Slices?
Un slice es una vista dinámica sobre un array. No almacena datos, sino una referencia a un array subyacente. Declaración:
slice := []int{1, 2, 3}
fmt.Println(len(slice)) // Salida: 3Los slices tienen tres propiedades: len (cantidad de elementos), capacity (tamaño del array subyacente) y pointer al array.
Ejemplo práctico:
slice := []int{10, 20, 30}
slice = append(slice, 40)
fmt.Println(len(slice), cap(slice)) // Salida: 4 4Aquí, append aumenta tanto len como capacity porque el slice puede crecer.
Capacity vs Len: ¿Qué significan?
len(slice): Número de elementos válidos.cap(slice): Tamaño máximo del array subyacente.
arr := [10]int{}
slice := arr[:5]
fmt.Println(cap(slice)) // Salida: 10En este caso, el slice tiene 5 elementos (len=5), pero su capacidad es 10 porque usa todo el array subyacente.
Cambios en la capacidad:
slice := []int{1, 2}
slice = append(slice, 3, 4, 5)
fmt.Println(cap(slice)) // Salida: 5Cuando el slice crece, su capacidad se ajusta, pero si se excede, se allocate un nuevo array.
Aliasing: El Truco Oculto
Los slices pueden apuntar al mismo array subyacente, causando aliasing. Modificar uno afecta al otro.
arr := [5]int{1, 2, 3, 4, 5}
slice1 := arr[:3]
slice2 := arr[2:4]
slice1[0] = 99
fmt.Println(slice2) // Salida: [3 4] -> [99 4]Aquí, slice1 y slice2 comparten el mismo array, así que cambiar slice1[0] modifica arr[0], que está en slice2.
Error común:
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[:]
arr[0] = 0
fmt.Println(slice[0]) // Salida: 0El slice refleja cambios en el array, incluso si fue creado como copia inicial.
Buenas prácticas y errores comunes
- Usa arrays para datos fijos: Si conoces el tamaño exacto, los arrays son más eficientes.
- Evita aliasing no intencionado: Si un slice modifica datos, asegúrate de que sea esperado.
- Mide capacidad con
cap: Si necesitas prealocar memoria, usamake([]T, len, cap).
Conclusión
Arrays y slices son fundamentales en Go, pero sus diferencias son cruciales:
- Arrays: Fijos, copian datos.
- Slices: Dinámicos, comparten memoria (aliasing).
Saber cuándo usar cada uno y entender capacity y len te ahorrará errores en la práctica. Prueba los ejemplos con run:go para ver cómo estos conceptos aplican en tiempo real.
Siguiente paso
Si quieres dominar más, explora structs o maps en Go, que también usan slice para almacenar datos dinámicos.
DUGLAS MORENO
Comentarios (0)
Sé el primero en comentar.