Os slices em Go são semelhantes a listas ou arrays noutras linguagens. Contêm vários elementos de um tipo específico (ou interface).
Os slices em Go baseiam-se em arrays. Os arrays têm um tamanho fixo. Um slice, por outro lado, é uma vista flexível e de tamanho dinâmico dos elementos de um array.
Um slice escreve-se como []T, em que T é o tipo dos elementos do slice:
var empty []int // an empty slice
withData := []int{0,1,2,3,4,5} // a slice pre-filled with some data
Podes obter ou definir um elemento num determinado índice com base zero usando a notação de parênteses retos:
withData[1] = 5
x := withData[1] // x is now 5
Podes criar um novo slice a partir de um slice existente obtendo um intervalo de elementos. Mais uma vez, usando a notação de parênteses retos, mas especificando tanto um índice inicial (inclusive) como um índice final (exclusive). Se não especificares um índice inicial, este assume o valor 0. Se não especificares um índice final, este assume o comprimento do slice.
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}
Podes adicionar elementos a um slice usando a função append.
Abaixo, acrescentamos 4 e 2 ao slice a.
a := []int{1, 3}
a = append(a, 4, 2)
// => []int{1,3,4,2}
A função append devolve sempre um novo slice e, quando só queremos acrescentar elementos a um slice existente, é comum voltar a atribuí-lo à variável do slice que passamos como primeiro argumento, como fizemos acima.
A função append também pode ser usada para combinar dois slices:
nextSlice := []int{100,101,102}
newSlice := append(withData, nextSlice...)
// => []int{0,1,2,3,4,5,100,101,102}
Normalmente, as funções em Go aceitam apenas um número fixo de argumentos. No entanto, também é possível escrever funções variádicas em Go.
Uma função variádica é uma função que aceita um número variável de argumentos.
Se o tipo do último parâmetro numa definição de função for precedido de reticências ..., então a função pode aceitar qualquer número de argumentos para esse parâmetro.
func find(a int, b ...int) {
// ...
}
Na função acima, o parâmetro b é variádico e podemos passar 0 ou mais argumentos a b.
find(5, 6)
find(5, 6, 7)
find(5)
O parâmetro variádico tem de ser o último parâmetro da função.
As funções variádicas funcionam convertendo o número variável de argumentos num slice do tipo do parâmetro variádico.
Aqui está um exemplo de implementação de uma função 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 []
}
Na linha find(89, 90, 91, 95) do programa acima, os argumentos variáveis da função find são 90, 91 e 95.
A função find espera um parâmetro variádico do tipo int depois de num.
Por isso, estes três argumentos serão convertidos pelo compilador num slice do tipo int, []int{90, 91, 95}, e depois será passado à função find como nums.
Por vezes, já tens um slice e queres passá-lo a uma função variádica.
Podes conseguir isso passando o slice seguido de ....
Isso diz ao compilador para usar o slice tal como está dentro da função variádica.
O passo descrito acima, em que é criado um slice, é simplesmente omitido neste caso.
list := []int{1, 2, 3}
find(1, list...) // "find" defined as shown above
Como futura maga, a Elyse precisa de praticar alguns conceitos básicos. Tem uma pilha de cartas que quer manipular.
Para simplificar um pouco, só usa as cartas de 1 a 10.
Quando está a praticar com as cartas, a Elyse gosta de começar pelas suas três cartas favoritas do baralho: 2, 6 e 9.
Escreve uma função FavoriteCards que devolve um slice com essas cartas por essa ordem.
cards := FavoriteCards()
fmt.Println(cards)
// Output: [2 6 9]
Devolve a carta na posição index da pilha indicada.
card := GetItem([]int{1, 2, 4, 1}, 2) // card == 4
Se o índice estiver fora dos limites (ou seja, se for negativo ou ultrapassar o fim da pilha), queremos devolver -1:
card := GetItem([]int{1, 2, 4, 1}, 10) // card == -1
Por convenção em Go, devolve-se um erro em vez de devolver um valor "fora dos limites".
Aqui, o valor "fora dos limites" é -1 quando se espera um número inteiro positivo.
Ao devolver um erro, considera-se idiomático devolver o zero value juntamente com o erro.
Devolver um erro com o valor devolvido adequado será abordado num exercício futuro.
Troca a carta na posição index pela nova carta fornecida e devolve a pilha ajustada.
Repara que isto vai modificar o slice que recebes, o que é o comportamento esperado.
index := 2
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 6 1]
Se o índice estiver fora dos limites (ou seja, se for negativo ou ultrapassar o fim da pilha), queremos acrescentar a nova carta ao fim da pilha:
index := -1
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 4 1 6]
Adiciona a(s) carta(s) indicada(s) no parâmetro value ao topo da pilha.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice, 5, 1)
fmt.Println(cards)
// Output: [5 1 3 2 6 4 8]
Se não for dado nenhum argumento para o parâmetro value, o resultado é igual ao slice original.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice)
fmt.Println(cards)
// Output: [3 2 6 4 8]
Remove a carta na posição index da pilha e devolve a pilha.
Repara que isto pode modificar o slice que recebes, o que não faz mal.
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 2)
fmt.Println(cards)
// Output: [3 2 4 8]
Se o índice estiver fora dos limites (ou seja, se for negativo ou ultrapassar o fim da pilha), queremos deixar a pilha inalterada:
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 11)
fmt.Println(cards)
// Output: [3 2 6 4 8]
Inscreve-te no Exercism para aprenderes e dominares Go com 34 conceitos165 exercícios, e mentoria humana real, tudo grátis.