Arrays vs Slices en Go: Difference Crítica que Debes Conocer Go

Arrays vs Slices en Go: Difference Crítica que Debes Conocer

DUGLAS MORENODUGLAS MORENO 👁 20

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: 5

Aquí, 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: 3

Los 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 4

Aquí, 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: 10

En 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: 5

Cuando 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: 0

El slice refleja cambios en el array, incluso si fue creado como copia inicial.

Buenas prácticas y errores comunes

  1. Usa arrays para datos fijos: Si conoces el tamaño exacto, los arrays son más eficientes.
  2. Evita aliasing no intencionado: Si un slice modifica datos, asegúrate de que sea esperado.
  3. Mide capacidad con cap: Si necesitas prealocar memoria, usa make([]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.

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario