Los slices de Go son similares a los arrays de otros lenguajes. Contienen varios elementos de un tipo específico (o de una interfaz).
Los slices de Go se basan en los arrays. Los arrays tienen un tamaño fijo. Un slice, en cambio, es una vista flexible y de tamaño dinámico de los elementos de un array.
Un slice se escribe así: []T, donde T es el tipo de los elementos del slice:
var empty []int // an empty slice
withData := []int{0,1,2,3,4,5} // a slice pre-filled with some data
Puedes obtener o asignar un elemento en un índice concreto que empieza en cero usando la notación de corchetes:
withData[1] = 5
x := withData[1] // x is now 5
Puedes crear un slice nuevo a partir de un slice existente obteniendo un rango de elementos. De nuevo con la notación de corchetes, pero indicando tanto un índice inicial (incluido) como un índice final (excluido). Si no indicas un índice inicial, se usa 0 por defecto. Si no indicas un índice final, se usa la longitud del slice por defecto.
newSlice := withData[2:4]
// => []int{2,3}
newSlice := withData[:2]
// => []int{0,1}
newSlice := withData[2:]
// => []int{2,3,4,5}
newSlice := withData[:]
// => []int{0,1,2,3,4,5}
Puedes añadir elementos a un slice con la función append.
A continuación añadimos 4 y 2 al slice a.
a := []int{1, 3}
a = append(a, 4, 2)
// => []int{1,3,4,2}
append siempre devuelve un slice nuevo y, cuando lo único que queremos es añadir elementos a un slice que ya existe, lo habitual es reasignar el resultado a la variable de slice que pasamos como primer argumento, como hicimos arriba.
append también se puede usar para combinar dos slices:
nextSlice := []int{100,101,102}
newSlice := append(withData, nextSlice...)
// => []int{0,1,2,3,4,5,100,101,102}
Normalmente, las funciones de Go solo aceptan un número fijo de argumentos. Sin embargo, también es posible escribir funciones variádicas en Go.
Una función variádica es una función que acepta un número variable de argumentos.
Si el tipo del último parámetro de la definición de una función va precedido de puntos suspensivos ..., la función puede aceptar cualquier número de argumentos para ese parámetro.
func find(a int, b ...int) {
// ...
}
En la función anterior, el parámetro b es variádico y podemos pasarle 0 o más argumentos.
find(5, 6)
find(5, 6, 7)
find(5)
El parámetro variádico tiene que ser el último parámetro de la función.
Las funciones variádicas funcionan convirtiendo el número variable de argumentos en un slice del tipo del parámetro variádico.
Aquí tienes un ejemplo de implementación de una función variádica.
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
return
}
}
fmt.Println(num, "not found in ", nums)
}
func main() {
find(89, 90, 91, 95)
// =>
// type of nums is []int
// 89 not found in [90 91 95]
find(45, 56, 67, 45, 90, 109)
// =>
// type of nums is []int
// 45 found at index 2 in [56 67 45 90 109]
find(87)
// =>
// type of nums is []int
// 87 not found in []
}
En la línea find(89, 90, 91, 95) del programa anterior, los argumentos en número variable de la función find son 90, 91 y 95.
La función find espera un parámetro variádico de tipo int después de num.
Por lo tanto, el compilador convertirá estos tres argumentos en un slice de tipo int, []int{90, 91, 95}, y luego lo pasará a la función find como nums.
A veces ya tienes un slice y quieres pasárselo a una función variádica.
Esto se consigue pasando el slice seguido de ....
Eso le indica al compilador que use el slice tal cual dentro de la función variádica.
En este caso, el paso descrito antes en el que se crea un slice simplemente se omite.
list := []int{1, 2, 3}
find(1, list...) // "find" defined as shown above
Como aspirante a maga, Elyse necesita practicar algunos conceptos básicos. Tiene una pila de cartas que quiere manipular.
Para ponérselo un poco más fácil, solo usa las cartas del 1 al 10.
Cuando practica con sus cartas, a Elyse le gusta empezar con sus tres cartas favoritas de la baraja: el 2, el 6 y el 9.
Escribe una función FavoriteCards que devuelva un slice con esas cartas en ese orden.
cards := FavoriteCards()
fmt.Println(cards)
// Output: [2 6 9]
Devuelve la carta en la posición index de la pila dada.
card := GetItem([]int{1, 2, 4, 1}, 2) // card == 4
Si el índice está fuera de los límites (es decir, si es negativo o posterior al final de la pila), queremos devolver -1:
card := GetItem([]int{1, 2, 4, 1}, 10) // card == -1
Por convención en Go, se devuelve un error en lugar de devolver un valor «fuera de los límites».
Aquí el valor «fuera de los límites» es -1 cuando se espera un entero positivo.
Al devolver un error, se considera idiomático devolver el zero value junto con el error.
Devolver un error con el valor devuelto adecuado se tratará en un ejercicio futuro.
Intercambia la carta en la posición index por la nueva carta proporcionada y devuelve la pila ajustada.
Ten en cuenta que esto modificará el slice de entrada, que es el comportamiento esperado.
index := 2
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 6 1]
Si el índice está fuera de los límites (es decir, si es negativo o posterior al final de la pila), queremos añadir la nueva carta al final de la pila:
index := -1
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 4 1 6]
Añade la(s) carta(s) especificada(s) en el parámetro value a la parte superior de la pila.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice, 5, 1)
fmt.Println(cards)
// Output: [5 1 3 2 6 4 8]
Si no se da ningún argumento para el parámetro value, el resultado es igual al slice original.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice)
fmt.Println(cards)
// Output: [3 2 6 4 8]
Elimina la carta en la posición index de la pila y devuelve la pila.
Ten en cuenta que esto puede modificar el slice de entrada, lo cual está bien.
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 2)
fmt.Println(cards)
// Output: [3 2 4 8]
Si el índice está fuera de los límites (es decir, si es negativo o posterior al final de la pila), queremos dejar la pila sin cambios:
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 11)
fmt.Println(cards)
// Output: [3 2 6 4 8]
Regístrate en Exercism para aprender y dominar Go con 34 conceptos165 ejercicios y mentoría humana real, todo gratis.