✊🏼 Slice em Golang 
Tags: go, beginners, tutorial
Published: 2020-06-03 22:30:12

⚠️ **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: 

{% link https://dev.to/linivecristine/arrays-em-golang-3cf1 %}

Agora vamos entrar no maravilhoso mundo dos slices.

```golang

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.   

```golang

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##

```golang

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. 

```golang

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:

```golang

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:

```golang

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.

```golang

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.  

```golang

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.**

 ```golang

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.


 ```golang

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. 

 ```golang

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.

 ```golang

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. 

 ```golang

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: 

 ```golang

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.

 ```golang

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.

 ```golang

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.

 ```golang
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:
 ```golang
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](https://youtu.be/WiGU_ZB-u0w)**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d0f86n1lx10q63l17b8i.gif)