Un slice
("rebanada" en español), viene a ser un segmento o una porción de un array. En la práctica, un slice
nos ofrece nuevas posibilidades para tratar con colecciones de datos.
Asignando rebanadas
En el siguiente ejemplo vamos a crear un array con una serie de elementos, y, a continuación, vamos a extraer una porción o rebanada de este array y se la asignaremos a un slice
, el cual crearemos por inferencia.
package main import "fmt" func main() { // Creacion de un slice por inferencia // a partir de un array miArray := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} miSlice := miArray[3:7] fmt.Printf("miArray: %T %v - len:%v - cap:%v\n", miArray, miArray, len(miArray), cap(miArray)) fmt.Printf("miSlice: %T %v - len:%v - cap:%v\n", miSlice, miSlice, len(miSlice), cap(miSlice)) }
Aparentemente, el slice
podría parecer un array normal con la copia del fragmento extraido del array. Pero cuando ejecutamos el código, veremos algunas diferencias:
$ go run slices.go miArray: [10]int [0 1 2 3 4 5 6 7 8 9] - len:10 - cap:10 miSlice: []int [3 4 5 6] - len:4 - cap:7
- El
slice
no tiene un tamaño definido ([]int
) - La capacidad del
slice
es mayor que la longitud del mismo: se han asignado cuatro elementos (longitud), pero su capacidad es de 7.
Esto significa que el slice
puede redimensionarse dinámicamente, es decir, que puede variar de tamaño. Esto supone una ventaja muy grande con respecto a los arrays, que son estáticos y no pueden variar de tamaño.
Creación de un slice
Un slice
se puede crear de varias maneras:
// Creacion de un slice por inferencia // a partir de un array miArray := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} miSlice := miArray[3:7] // Declaracion de un slice y posterior asignacion // Tendra longitud 3 y capacidad 3 var miSlice2 []int miSlice2 = []int{1, 2, 3} // *** FORMA RECOMENDADA *** // Creacion de un slice con longitud 3 y capacidad 3 miSlice3 := make([]byte, 3) // Creacion de un slice con longitud 3 y capacidad 6 miSlice4 := make([]float64, 3, 6)
A la hora de crear un slice
es recomendable utilizar la función make()
, ya que aporta una mejor legibilidad en el código, y porque permite controlar tanto su tamaño como su capacidad.
Asignación de datos a un slice
Existen varias maneras de asignar datos a un slice:
// Extrayendo una porcion a partir de un array miSlice = miArray[3:7] // Asignando un slice ad-hoc miSlice2 = []int{1, 2, 3}
Agregando nuevos valores al slice
Un slice
puede crecer dinámicamente, agregando valores según sean necesarios. Esto se consigue mediante la función append()
miSlice5 := []float64{12.2, 15.5, 18.9} // Agregacion de nuevos valores miSlice5 = append(miSlice5, 21.4, 23.7, 7.5) // Ahora miSlice5 contiene [12.2 15.5 18.9 21.4 23.7 7.5]
Copiando valores a un slice
Existen diferentes maneras para copiar valores a un slice
:
// Copia los elementos de un array miSlice := miArray[:] // Copia entre slices, mediante asignacion miSlice2 = miSlice // Metodo recomendado para copiar entre slices miSlice5 := []float64{12.2, 15.5, 18.9} miSlice7 := make([]float64, 3) copy(miSlice7, miSlice5)
La función copy()
es la forma recomendada para copiar todos los valores de un slice
a otro.
Nota importante: Los datos a copiar deben ser del mismo tipo que el tipo del slice
Eliminando elementos de un slice
miSlice8 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // Eliminar los dos primeros elementos // 3, 4, 5, 6, 7, 8, 9, 10 miSlice8 = miSlice8[2:] // Eliminar los dos ultimos elementos // 3, 4, 5, 6, 7, 8 miSlice8 = miSlice8[:6]
Unión de varios slices
La sintaxis de la función append()
es la siguiente:
append(slice, valor1, valor2, valor_n)
Sin intentamos unir dos slices
dará un error, pues a partir del segundo parámetro espera un valor del mismo tipo que el slice
, no un tipo slice
. Es decir, espera una lista de elementos y no un slice
.
Para añadir un slice
mediante la función append()
, debemos utilizar la siguiente sintaxis:
append(slice1, slice2...)
Los puntos suspensivos después del nombre del slice
, indican a Go que descomponga dicho slice
por la lista de elementos que contiene.
Veamos un ejemplo:
// Adicion de varios slices slice1 := []string{"Rafael", "Eduardo"} slice2 := []string{"Cristina", "Antonio"} slice3 := []string{"Lucía", "José", "Víctor", "Ana"} slice3 = append(slice3, slice1...) slice3 = append(slice3, slice2...) fmt.Println("slice3: ", slice3)
El resultado será el siguiente:
slice3: [Lucía José Víctor Ana Rafael Eduardo Cristina Antonio]
Slices como referencias a un array
Cuando trabajamos con slices
, en realidad estamos trabajando con una referencia a un array. Por tanto, el slice esta apuntando a la dirección de memoria del array que contiene los datos, y, por tanto, los cambios en algún elemento afectarán a ambos.
En el siguiente ejemplo se crea un array con una lista de nombres. A continuación, se crean dos slices
, cada uno de los cuales referencia a una porción del array. Después, se cambia el elemento "Cristina" por "Nerea" en el segundo slice
. Al ser una referencia, en realidad se está modificando en el array, por lo que el elemento cambia tanto para el array como para los slices
.
arr := [5]string{"Rafael", "Edu", "Cristina", "Antonio", "Lucía"} // ["Rafael", "Edu", "Nerea"] sl1 := arr[:3] // ["Nerea", "Antonio", "Lucía"] sl2 := arr[2:] fmt.Printf("arr: %v\n", arr) fmt.Printf("sl1: %v\n", sl1) fmt.Printf("sl2: %v\n", sl2) // Cambiar "Cristina" por "Nerea" sl2[0] = "Nerea" fmt.Printf("arr: %v\n", arr) fmt.Printf("sl1: %v\n", sl1) fmt.Printf("sl2: %v\n", sl2)
El resultado será el siguiente:
arr: [Rafael Edu Cristina Antonio Lucía] sl1: [Rafael Edu Cristina] sl2: [Cristina Antonio Lucía] arr: [Rafael Edu Nerea Antonio Lucía] sl1: [Rafael Edu Nerea] sl2: [Nerea Antonio Lucía]
Enlaces de interés
- A tour of Go - Slices: https://tour.golang.org/moretypes/7
- Golang Book - Slices: https://www.golang-book.com/books/intro/6#section2
- Go by Example - Slices: https://gobyexample.com/slices
- SliceTricks: https://github.com/golang/go/wiki/SliceTricks
No hay comentarios:
Publicar un comentario