En este post vamos a ir viendo como se podrian hacer las cosas mas habituales con los Arrays o Slices, como puede ser recorrerlos, veremos tambien como podemos pasar de uno a otro para la optimización, sin mucho mas empezamos.
Recorrer un array o slice
Empecemos por el caso más habitual y es la necesidad de recorrer el contenido de un array, en este punto voy a adelantar alguna otra cosa que no es solo de Array o Slices, pero creo que es mejor verlo en esta parte.
Para recorrer un array, tipicamente lo hacemos un bucle for, pues en este caso Go tiene un proceso muy similar específico (aunque se podria simular un for normal, haciendo el código a mano pero me parece innecesario, con el código lo vereis mejor)
rangers := []string{"Ranger Rosa", "Ranger Amarillo"}
for index, ranger := range rangers {
fmt.Println("El indice o posicion es: ", index)
fmt.Println("El Ranger de esa posicion es:", ranger)
}
Con un resultado similar a este:
Como vemos aqui tenemos un par de palabras reservadas que no habiamos usado: for y range, mas o menos os podéis imaginar la funcion que tiene cada una, básicamente esto quiere decir "Por cada índice y ranger dentro del rango de rangers....."
Bastante sencillo no?? Si os fijais tenemos la declaración corta de variables :=, lo que esta haciendo es asignar en cada vuelta, el índice y el valor en los nombres de variables que hemos puesto(podrian ser otros perfectamente).
Y si no queremos el índice?? Básicamente ignoramos el resultado:
for _, ranger := range rangers {
fmt.Println("El Ranger de esa posicion es:", ranger)
}
El _ en Go es un valor especial(funciona igual que en Swift por ejemplo) con el que estamos indicando que ignore ese resultado que podemos obtener de una función o cualquier otro proceso como puede ser este que acabamos de ver de recorrer un array.
Separando un array
O mas bien crear un subarray con parte del array original, es decir, veamos como partir un array para extrar el rango de posiciones que nos interese.
En go tenemos la posibilidad de seleccionar un rango de X posiciones dentro de un array, de una manera bastante sencilla:
miniRangers := rangers[:2]
fmt.Println("Hemos seleccionado del inicio a la posicion 2 sin incluirla:")
fmt.Println(miniRangers)
miniRangers2 := rangers[2:4]
fmt.Println("Hemos seleccionado desde la posicion 2 hasta la 4 sin incluirla:")
fmt.Println(miniRangers2)
miniRangers3 := rangers[4:]
fmt.Println("Hemos seleccionado desde la 4 hasta el final")
fmt.Println(miniRangers3)
Tambien es posible asignar al mismo array o resumiendo cortar el array:
rangers := []string{"Ranger Rosa", "Ranger Amarillo", "Ranger Rojo", "Ranger Verde", "Ranger Negro"}
rangers = rangers[2:4]
fmt.Println("Hemos seleccionado del inicio a la posicion 2 sin incluirla:")
fmt.Println(rangers)
Tamaño y Capacidad
Estos ya los hemos visto:
fmt.Println(len(rangers))//Para el tamaño
fmt.Println(len(rangers))//Capacidad
Añadir
Tambien hemos visto como añadir, ya sea en un array hasta su tamaño designado y en un slice cuando no esta inicializado:
var rangersDesignados [2]string
rangersDesignados = append(rangersDesignados,"R.Rojo","R.Verde")
rangersSlices = make([]string,2,10)
append(rangersSlices,"R.Rojo","R.Verde")
Eliminar
Siento decir que aqui el lenguaje nos falla un poco, ya que no ofrece ningun método ya preparado para esto, como tal ya tenemos que jugar nosotros. En esta página:SliceTricks
Tenemos alguna forma de hacer las operaciones mas comunes de eliminar, cortar, etc de manera eficiente.
Copiar(Importante)
En un principio esto puede no parecer nada, estamos hablando de copiar un array o slice en otro......bueno pues no es tan simple, ¿recordáis lo que comentamos en el post anterior sobre tamaño y capacidad? Por refrescar rápidamente, el tamaño era la cantidad de elementos que tenia un slice o array y la capacidad la reserva de elementos que puede contener, es decir, la cantidad máxima de elementos que puede tener. Recordemos que Go lo que hace es reservar un espacio en memoria para almacenar una cantidad aproximada de datos, lo importante venia a la hora de aumentar, como tal el slice comentamos que al aumentar lo que hacia era reservarse el doble de la capacidad que tenia anteriormente. Esto con slices pequeños esta muy bien, pero ¿y si tenemos un slice de 1000 elementos? En cuanto añadamos 1 más se reservara un espacio de 2000.
Pues bien con este escenario tenemos la accion de copiar como solución, lo que hacemos es copiar un array en otro con la capacidad ajustada a lo que queramos, la forma de usarlo es simple:
copy(destino, origen)
Bastante simple no? Pues veamos un ejemplo y apliquemos un poco de lógica para optimizar el consumo:
//Creamos dos slices
slice := []int{1, 2, 3, 4}
copia := make([]int, 4)
copy(copia, slice)
fmt.Println(slice)
fmt.Println(copia)
Como vemos hemos creado un slice con la forma corta, con contenido, y otro vacio con un tamaño y capacidad de 4. Si imprimimos el contenido todo estaría normal, pero un detalle a tener en cuenta es que realmente copy tiene en cuenta la capacidad del slice de destino (en este caso copia), como le hemos puesto una capacidad de 4, nos copia todo el contenido. Pongamos un ejemplo si ponemos menos:
//Si cambiaramos copia con otra longitud
copia2 := make([]int, 2)
copy(copia2, slice)
fmt.Println(slice)
fmt.Println(copia2)
//Veriamos como solo nos copia 2 elementos,
Lo mejor es controlar el tamaño(no la capacidad ojo), del slice origen y usar eso para crear el destino:
//para no equivocarnos lo ideal seria
copia3 := make([]int, len(slice))
copy(copia3, slice)
fmt.Println(slice)
fmt.Println(copia3)
//Con esto si cambia el tamaño del slice la copia tambien.
//Como buena practica, aunque segun el entorno, es añadir el doble del tamaño a la capacidad
copia4 := make([]int, len(slice), len(slice)*2) //O con la capacidad segun el caso
copy(copia4, slice)
fmt.Println(slice)
fmt.Println(copia4)
Bueno creo que por el momento vamos a dejar los arrays y slices para continuar con otras cosas, recordar mirar el link SliceTricks y en otro de mis post tengo algo mas de trabajo con arrays: Go Tricks I



