Go

Go

Tutorial Go: Arrays y slices

Go Arrays y slices ofrece una guía completa para manejar colecciones de datos en Go, cubriendo declaración, inicialización y manipulación eficiente.

Aprende Go GRATIS y certifícate

Declaración y uso de arrays

En Go, un array es una estructura de datos que almacena una secuencia de elementos del mismo tipo de longitud fija. La declaración de un array se realiza especificando el tipo de los elementos que contendrá y su tamaño. La sintaxis básica para declarar un array es:

var nombreArray [tamaño]tipo

Por ejemplo, la declaración de un array de cinco enteros se haría de la siguiente manera:

var numeros [5]int

En este caso, numeros es un array de enteros de tamaño cinco. Cada elemento del array se inicializa automáticamente al valor cero del tipo de dato, en este caso, 0 para los enteros.

Además de la declaración, es posible inicializar un array con valores específicos en el momento de su declaración. Esto se logra utilizando llaves {} y separando los valores por comas:

nombres := [3]string{"Ana", "Luis", "Carlos"}

En este ejemplo, nombres es un array de cadenas de tamaño tres, inicializado con los valores "Ana", "Luis" y "Carlos".

El acceso a los elementos de un array se realiza mediante un índice, comenzando desde cero. Por ejemplo, para acceder al segundo elemento del array nombres, se utiliza:

segundoNombre := nombres[1]

Es importante destacar que los arrays en Go son de tamaño fijo y no pueden redimensionarse una vez creados. Esto significa que no se pueden agregar o eliminar elementos de un array sin crear uno nuevo.

Para recorrer un array y realizar operaciones sobre sus elementos, se puede utilizar un bucle for. La estructura típica de un bucle para iterar sobre un array es:

for i := 0; i < len(numeros); i++ {
    fmt.Println(numeros[i])
}

Aquí, len(numeros) devuelve la longitud del array, y el bucle imprime cada elemento del array numeros.

En situaciones donde se necesita una estructura de datos con tamaño dinámico, se recomienda utilizar slices, que se tratan en otra sección de esta lección. Los arrays son útiles cuando se requiere un tamaño fijo y control estricto sobre el uso de memoria.

Introducción y manejo de slices

En Go, los slices son una abstracción más flexible y poderosa que los arrays, permitiendo manejar colecciones de elementos de tamaño dinámico. Mientras que los arrays tienen un tamaño fijo, los slices pueden crecer y decrecer según sea necesario. Un slice es esencialmente una referencia a una parte de un array, y consta de tres componentes: un puntero al primer elemento del array que representa, una longitud y una capacidad. La longitud es el número de elementos que el slice contiene actualmente, mientras que la capacidad es el número de elementos en el array subyacente, contando desde el primer elemento del slice.

Para declarar un slice, se puede utilizar la función incorporada make, que permite crear un slice especificando su longitud y capacidad inicial:

nombres := make([]string, 5, 10)

En este ejemplo, nombres es un slice de cadenas con una longitud inicial de 5 y una capacidad de 10. Si no se especifica la capacidad, esta es igual a la longitud:

numeros := make([]int, 5)

Aquí, numeros es un slice de enteros con una longitud y capacidad de 5.

Los slices también pueden crearse a partir de un array o de otro slice. Por ejemplo, dada la declaración de un array de enteros:

array := [5]int{1, 2, 3, 4, 5}

Se puede crear un slice que incluya todos los elementos del array:

slice := array[:]

O solo una parte de ellos:

subslice := array[1:4]

Este último ejemplo crea un slice que contiene los elementos del índice 1 al 3 del array original, es decir, [2, 3, 4].

Una de las características más útiles de los slices es la capacidad de añadir elementos dinámicamente usando la función append. Esta función devuelve un nuevo slice que contiene los elementos del original más los nuevos elementos añadidos:

numeros = append(numeros, 6, 7, 8)

En este caso, se añaden los números 6, 7 y 8 al slice numeros. Si la capacidad del slice original no es suficiente para contener los nuevos elementos, Go asigna un nuevo array con el doble de la capacidad original, copia los elementos existentes y luego añade los nuevos.

Al trabajar con slices, es importante entender que son referencias a arrays subyacentes. Esto significa que si dos slices refieren a la misma sección de un array, un cambio en uno de los slices puede afectar al otro. Por ejemplo:

s1 := []int{1, 2, 3, 4, 5}
s2 := s1[1:3]
s2[0] = 9

Después de modificar s2, el array subyacente de s1 también refleja este cambio, por lo que s1 se convierte en [1, 9, 3, 4, 5].

La función copy se utiliza para copiar elementos de un slice a otro, lo cual es útil para evitar la modificación no intencionada de datos compartidos:

s3 := make([]int, len(s1))
copy(s3, s1)

Con esta operación, s3 es una copia independiente de s1, y los cambios en s3 no afectan a s1. Los slices son una herramienta esencial en Go para manejar colecciones de datos de tamaño variable de manera eficiente y controlada.

Operaciones comunes: agregar(append), copiar(copy), segmentar(slicing)

En Go, los slices son fundamentales para trabajar con colecciones de datos de tamaño dinámico, y tres de las operaciones más comunes que se realizan sobre ellos son agregar, copiar y segmentar.

Agregar

Para agregar elementos a un slice, se utiliza la función append. Esta función toma un slice y uno o más elementos a añadir, devolviendo un nuevo slice con los elementos agregados. Si la capacidad del slice original es insuficiente, se asigna un nuevo array con mayor capacidad. El uso de append es sencillo:

nombres := []string{"Ana", "Luis"}
nombres = append(nombres, "Carlos")

En este ejemplo, "Carlos" se añade al slice nombres. Es importante notar que append devuelve un nuevo slice, por lo que es habitual reasignar el resultado a la variable original o a una nueva.

Copiar

La operación de copiar es útil cuando se necesita duplicar los elementos de un slice en otro, manteniendo una separación entre ambos. En Go, se utiliza la función copy, que toma dos slices como argumentos: el destino y el origen. El número de elementos copiados es el mínimo entre la longitud de ambos slices. Un ejemplo de uso es:

origen := []int{1, 2, 3}
destino := make([]int, len(origen))
copy(destino, origen)

Aquí, destino recibe una copia de los elementos de origen. Cambios en destino no afectan a origen, lo que garantiza que las modificaciones sean independientes.

Segmentar

La operación de segmentar permite crear un nuevo slice que hace referencia a un subconjunto de los elementos de un slice existente. La sintaxis para segmentar un slice es slice[low:high], donde low es el índice inicial y high es el índice final no inclusivo. Esta operación es eficiente porque el nuevo slice comparte el array subyacente con el original:

enteros := []int{0, 1, 2, 3, 4, 5}
subSlice := enteros[2:5]

En este caso, subSlice contiene los elementos [2, 3, 4], referenciando parte del slice enteros. Debido a que los slices comparten el mismo array subyacente, las modificaciones en subSlice afectarán a enteros, y viceversa, a menos que se haga una copia explícita.

Cada una de estas operaciones permite manejar los datos, maximizando la flexibilidad de los slices y permitiendo un control detallado sobre el uso de la memoria. Es crucial entender las implicaciones de estas operaciones para evitar errores comunes, como la modificación accidental de datos compartidos.

Aprende Go GRATIS online

Todas las lecciones de Go

Accede a todas las lecciones de Go y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Go y certifícate

Certificados de superación de Go

Supera todos los ejercicios de programación del curso de Go y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la declaración e inicialización de arrays en Go.
  • Saber cómo acceder y modificar elementos de un array.
  • Conocer las diferencias entre arrays y slices.
  • Aprender a declarar y utilizar slices, incluyendo make.
  • Realizar operaciones comunes con slices: agregar, copiar y segmentar.
  • Entender las implicaciones de memoria compartida en slices.
  • Dominio del uso de append y copy en la manipulación de slices.