DEV Community

Linive
Linive

Posted on

✊🏼 Slice em Golang

⚠️ Aviso: Antes de mais nada, você deve saber que os arrays são a base para os slices. Então se você nunca viu arrays:

Agora vamos entrar no maravilhoso mundo dos slices.


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

fmt.Println(sliceDeNumeros)

Se você leu o post sobre arrays, deve ter notado a semelhança entre os dois. A única diferença na declaração é que não estamos definindo o length do slice.


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

Já sabemos que em arrays não podemos adicionar novos elementos, pois o length dele não pode aumentar. Em slice não teremos esse problema, pois não declaramos qual será seu tamanho.

Você deve pensar no slice como um array sem tamanho definido, onde podemos adicionar novos elemento. Um slice é um array mais flexível.

Adicionando elementos a um slice


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

sliceDeNumeros = append(sliceDeNumeros, 6)
fmt.Println(sliceDeNumeros)

//Resultado: 1, 2, 3, 4, 5, 6

append significa adicionar, e é exatamente isso que queremos fazer, adicionar um elemento a nossa slice. Então chamamos a funcionalidade append e depois indicamos onde será adicionado: sliceDeNumeros e quem será adicionado: 6.

Quem será adicionado é um detalhe importante.

O nosso slice é do tipo slice of int, ou seja, é um slice formado por elementos int. Então só podemos adicionar números inteiros a ele.


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

sliceDeNumeros = append(sliceDeNumeros, 6.5)
sliceDeNumeros = append(sliceDeNumeros, "a")

//Nenhum dos dois casos pode ser realizado

Outro exemplo:


bairros := []string{"Pajuçara", "Ponta Verde", "Jacintinho", "Benedito Bentes"}

bairros = append(bairros, "Farol")

fmt.Println("São bairros de Maceó: " )
for indice, bairro := range bairros{
    fmt.Printf("%v - %v\n", indice + 1, bairro)
}

/*
Resultado:
São bairros de Maceó:
1 - Pajuçara
2 - Ponta Verde
3 - Jacintinho
4 - Benedito Bentes
5 - Farol
*/

Se quisermos pegar apenas um dos elemento:


bairros := []string{"Pajuçara", "Ponta Verde", "Jacintinho", "Benedito Bentes"}

fmt.Println("É um bairro de Maceó: ", bairros[0] )

//Resultado: É um bairros de Maceó: Pajuçara

Tem uma coisa que precisamos entender sobre os slices. Por baixo dos panos um slice nada mais é quem um array, quando adicionamos um novo elemento a um slice, seu array escondido é jogado fora e um novo é criado. Todas as vezes que adicionarmos elementos a um slice, um array será descartado e um novo será criado.

O array será descartado porque seu tamanho é imutável.

Agora imagine um slice com centenas de elementos e precisamos adicionar novos dados a cada 60 segundos. A cada minuto um array gigantesco será descartado e outro será criado, essa ação irá demandar muito custo computacional, deixando nosso programa pesado.

Não se preocupe, pois temos a solução para seu problema.

Make

Podemos utilizar o make. Com o ele conseguimos definir a capacidade do array subjacente a nossa slice. Podemos criar um slice onde seu array subjacente terá length 5 e capacidade 10.

Mas qual é a diferença entre length e capacidade? Vamos ver na prática.


var numeros = make([]int, 5, 10)

Estou declarando um slice of int, com length 5 e capacidade 10. O tamanho desse slice é 5, eu tenho espaço garantido para 5 elemento.


var numeros = make([]int, 5, 10)

numeros[0], numeros[1], numeros[2], numeros[3], numeros[4] = 1, 2, 3, 4, 5
fmt.Println(numeros,"-", len(numeros))

//Resultado: [1 2 3 4 5]- 5 

Se eu deixar de declarar um dos elemento, ele será zero, assim como nos arrays.

A novidade vem agora. Já utilizamos todos os elementos disponíveis, tínhamos 5. Agora se quisermos adicionar novos elementos, vamos ter que utilizar o append.

Acabamos de aprender que quando inserimos um novo elemento a um slice, seu array é jogado fora. Mas não nesse caso, pois definimos sua capacidade. Capacidade é a quantidade de novos elementos que podem ser adicionados ao slice sem seu array ser jogado fora.


var numeros = make([]int, 5, 10)

numeros[0], numeros[1], numeros[2], numeros[3], numeros[4] = 1, 2, 3, 4, 5
numeros = append(numeros, 6)

fmt.Println(numeros,"-", len(numeros), "-", cap(numeros))
//Resultado: [1 2 3 4 5 6] - 6 - 10

Podemos adicionar até 10 elementos ao slice antes do seu array ser jogado fora.


var numeros = make([]int, 5, 10)

numeros[0], numeros[1], numeros[2], numeros[3], numeros[4] = 1, 2, 3, 4, 5
numeros = append(numeros, 6, 7, 8, 9, 10)

fmt.Println(numeros,"-", len(numeros), "-", cap(numeros))
//Resultado: [1 2 3 4 5 6] - 10 - 10

Chegamos a capacidade máxima. Quando o próximo elemento for adicionado, o array será descartado e um novo será criado, a diferença é que sua capacidade irá dobrar.


var numeros = make([]int, 5, 10)

numeros[0], numeros[1], numeros[2], numeros[3], numeros[4] = 1, 2, 3, 4, 5
numeros = append(numeros, 6, 7, 8, 9, 10, 11)

fmt.Println(numeros,"-", len(numeros), "-", cap(numeros))
//Resultado: [1 2 3 4 5 6] - 11 - 20

Tipos

Agora vamos supor que eu quero unir duas slices.


numeros1 := []int{1, 2, 3, 4}
numeros2 := []int{5, 6, 7, 8}

numeros1 = append(numero1, numero2)

Essa ação não pode ser realizada. Estou tentando adicionar a slice numeros2 na slice numeros1, mas existe uma incompatibilidade de tipos.

Lembra que em go não podemos realizar operações com tipos diferentes?

As slices são tipo []int e são compostas por elementos int, ou seja, só podemos adicionar números inteiros. O tipo slice of int ([]int) é diferente do tipo int, isso quer dizer que não podemos simplesmente adicionar uma slice na outra. Não é possivel adicionar um []int onde deveria ser int.

Então precisamos pegar apenas os números que pertencem a slice numeros2, pois eles sim são inteiros.


numeros1 := []int{1, 2, 3, 4}
numeros2 := []int{5, 6, 7, 8}

numeros1 := append(numero1, numero2...)

fmt.Println(numeros1)

//Resultado: [1 2 3 4 5 6 7 8]

Basta colocar 3 pontos logo depois do nome da slice. Assim estamos acessando apenas os valores da slice e não ela em si.

Também podemos fazer assim:


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

numeros1 := append(numero1, []int{5, 6, 7, 8}...)

fmt.Println(numeros1)

//Resultado: [1 2 3 4 5 6 7 8]

Slice of Slice

Sabemos como pegar um elemento de forma individual, mas e se quisermos pegar um grupo de elementos da slice?

Vamos utilizar a slice of slice, fatiando a slice.


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

fmt.Println(numeros1[0:3])

//Resultado: [1 2 3]

numeros1[0:3] é assim que fatiamos a nossa slice, vamos indicar onde nossa fatia vai iniciar e onde ela irá terminar.

Um detalhe, indicamos que ela termina no índice 3 (número 4), mas apenas mostramos até o índice 2 (número 3). Isso é padrão, temos que ir um índice a mais do que queremos mostrar.

Pode ser um pouco confuso mesmo.


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

fmt.Println(numeros1[0:2])
fmt.Println(numeros1[1:4])
fmt.Println(numeros1[0: ])

/*
Resultado: 
[1 2]
[2 3 4]
[1 2 3 4]
*/

O nosso slice vai do índice 0 ao 3, mas no fmt.Println(numeros1[1:4]) indicamos o índice 4. Queremos mostrar o último elemento da slice (índice 3), mas por padrão devemos adicionar mais um, então temos que indicar o índice 4.

O fmt.Println(numeros1[0: ]) também mostra o último elemento, mas não indicamos nenhum índice. Essa é outra opção, deixamos o campo vazio.

Deletando elementos

Para deletar elementos vamos utilizar a slice of slice e o append.

Vamos criar duas fatias da slice, deixando os números que queremos deletar de fora e depois vamos juntar as duas fatias. Fica mais fácil na prática.

numeros1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

numeros1 = append(numeros1[0:4], numeros1[7:]...)
fmt.Println(numeros1)

//Resultado: [1 2 3 4 8 9 10]

A primeira fatia selecionou do número 1 ao 4 (índice 0 ao 3/ 4), já a segunda foi do número 8 ao 10 (índice 7 ao 9/ 10). Os números 5 ao 7 fora deixados de fora.

Para finalizar, damos um append nas duas fatias. Lembrando que queremos os elementos da fatia 2, pois eles são int.

Outro exemplo:

numeros1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

numeros1 = append(numeros1[1:5], numeros1[6:9]...)
fmt.Println(numeros1)

//Resultado: [2 3 4 5 7 8 9]

Já falamos muito por hoje, espero que tenham entendido tudo. Amanhã vamos conhecer os slices multidimensionais.

Se quiserem me acompanhar nos estudos 👉🏽 curso

Alt Text

Top comments (0)