Menu

Arrays en Golang: longitud fija, semántica de valor y slices

Un array de Go tiene una longitud fija que forma parte de su tipo, y se copia al asignarlo. Aprende a declarar, recorrer, comparar y pasar arrays, y por qué la mayor parte del código Go usa slices.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Declarar un array

Un tipo array se escribe [N]T: una longitud y luego un tipo de elemento. La longitud se fija en tiempo de compilación y forma parte del tipo.

Salida:

[90 0 0 0 75] 5
Tue
[5]int [2 3 5 7 11]
["" "b" "" "d" ""]

Un array siempre está inicializado por completo. Los elementos que no asignas tienen el valor cero del tipo del elemento: 0, "", false, nil.

Índices y límites

Los índices van de 0 a len(a)-1. Un índice constante fuera de rango es un error de compilación. Un índice variable fuera de rango provoca un panic en tiempo de ejecución.

var a [3]int
a[5] = 1 // compile error: invalid argument: index 5 out of bounds [0:3]

i := 5
a[i] = 1 // panic: runtime error: index out of range [5] with length 3

Recorrer un array

for i, v := range a visita cada elemento en orden. v es una copia del elemento, así que asignar a v no cambia el array. Escribe a través del índice.

Hay un detalle más propio de los arrays: range sobre un valor array evalúa una copia del array al principio. Si el cuerpo modifica elementos posteriores, v sigue mostrando los valores antiguos. Recorrer &a o a[:] evita la copia.

Los arrays son valores

Esta es la gran diferencia con los arrays de C, Java o JavaScript. Asignar un array copia todos sus elementos. Pasar un array a una función también lo copia.

Salida:

[1 2 3] [99 2 3]
[1 2 3]
[0 2 3]

Copiar es barato con arrays pequeños y caro con arrays grandes: pasar un [1_000_000]int por valor copia ocho megabytes. Pasa un puntero (*[N]T) o un slice (a[:]) cuando el array sea grande o la función tenga que modificarlo. Indexar a través de un puntero a array no necesita * explícito: a[0] funciona sobre un *[3]int.

Comparar arrays y usarlos como claves de map

Los arrays de elementos comparables admiten == y !=. Dos arrays son iguales cuando cada elemento es igual. Eso también los convierte en claves de map válidas, cosa que los slices no son.

Los arrays de longitudes distintas son tipos distintos y no se pueden comparar: [3]int{} == [4]int{} no compila (mismatched types [3]int and [4]int).

Arrays multidimensionales

Un array de arrays te da una cuadrícula fija. Toda la cuadrícula es un único bloque contiguo de memoria.

row[:] convierte la fila [3]rune en un slice []rune, que string() acepta.

Arrays frente a slices

Array [N]TSlice []T
Longitudfija, parte del tipocambia con append
Asignación y pasocopia todos los elementoscopia una cabecera pequeña, comparte los elementos
Valor ceroN elementos ceronil, longitud 0
==sí, elemento a elementosolo contra nil
Clave de mapno
Uso típicodatos de tamaño fijo: hashes, coordenadas, bufferscasi todo lo demás

En la práctica te encontrarás arrays sobre todo en unos pocos sitios: sha256.Sum256 devuelve un [32]byte, tablas de consulta cuyo tamaño nunca cambia, y como almacenamiento de respaldo de un slice. Recortar un array con a[:] o a[1:3] crea un slice que comparte su memoria; la página de slices explica qué implica compartirla.

Convertir entre arrays y slices

Convertir un slice en un array (Go 1.20) o en un puntero a array (Go 1.17) provoca un panic si el slice es más corto que la longitud del array: panic: runtime error: cannot convert slice with length 2 to array or pointer to array with length 3.

Errores comunes

  • Esperar que una función modifique un array que recibe como argumento. Recibe una copia. Pasa *[N]T o un slice.
  • Usar un array donde se espera un slice. []int{1, 2} es un slice, [2]int{1, 2} es un array. Una función que recibe []int no acepta un [2]int; pasa a[:].
  • Arrays grandes en un bucle range. for _, v := range bigArray copia primero todo el array. Recorre &bigArray o un slice.

Preguntas frecuentes

¿Cómo se declara un array en Go?

Escribe la longitud entre corchetes antes del tipo del elemento: var a [5]int crea cinco ceros. Con valores: a := [3]string{"x", "y", "z"}. Usa [...] para que el compilador cuente: a := [...]int{1, 2, 3} tiene tipo [3]int.

¿Qué diferencia hay entre un array y un slice en Go?

Un array tiene una longitud fija que forma parte de su tipo ([3]int y [4]int son tipos distintos) y se copia al asignarlo o pasarlo. Un slice ([]int) es una vista sobre un array subyacente con una longitud que puede cambiar mediante append, y copiar un slice copia solo la vista, no los elementos. La mayor parte del código Go usa slices.

¿Cómo obtengo la longitud de un array en Go?

Usa la función integrada len(a). Para un array es una constante en tiempo de compilación, así que puedes usarla en expresiones constantes. cap(a) devuelve el mismo número.

¿Se pueden comparar arrays en Go?

Sí, con == y !=, si el tipo del elemento es comparable. Dos arrays son iguales cuando todos sus elementos son iguales. Los arrays también pueden ser claves de un map. Los slices no se pueden comparar con == (salvo con nil); para ellos usa slices.Equal.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR