Loop for range em go
Tags: go, beginners, tutorial
Published: 2020-05-24 21:23:26

Hoje vamos falar um pouco mais sobre loops. 

Vocês já ouviram valar sobre o ``for range``? 

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

*Calma que não é esse tipo de ranger...*

Ele é outra versão do loop for, muito utilizado com slices, arrays, maps e strings. *O que esses tipos têm em comum?* São compostos por um grupo de outros elementos.

Ainda não vimos slices, arrays e maps, apenas sabemos que são tipos compostos, ou seja, formado por tipos primitivos. Mas já conhecemos bem o tipo string.

Sabemos que a string é uma cadeia de caracteres, ou runes, e que uma rune é do tipo ``int32``, podendo ter até 4 bytes. Já aprendemos a transformar caracteres em slice of bytes, sabemos que existe a tabela ASCII, o UTF-8 e o unicode, entre outras coisas. **Por isso vamos aprender o ``for range`` com strings**. 

**Esse é o ``for range``**:

```golang

serie := "modern family" 

for indice, valor := range serie {
  
    fmt.Printf("índice: %v - valor: %v\n", indice, valor)
}
/*
resultado:
índice: 0 - valor: 109 
índice: 1 - valor: 111 
índice: 2 - valor: 100
índice: 3 - valor: 101
índice: 4 - valor: 114
índice: 5 - valor: 110
índice: 6 - valor: 32
índice: 7 - valor: 102
índice: 8 - valor: 97
índice: 9 - valor: 109
índice: 10 - valor: 105
índice: 11 - valor: 108
índice: 12 - valor: 121
*/
```
O resultado foi numérico, se você leu o post de conversão 👇🏽: 
{% link https://dev.to/linivecristine/conversao-de-tipos-em-golang-198g %}

Já deve saber exatamente o que aconteceu, o tipo deixou de ser string e passou a ser int32, que é o tipo de um caractere. Esses números que saíram no resultado podem ser encontrados na tabela ASCII, o número 32, por exemplo, é referente ao espaço que existe na string.  

Vamos conhecer parte por parte do ``for range``.

```golang

serie := "modern family" 

for indice, valor := range serie {...}

```
O ``range`` vai percorrer toda a extensão da string, ele vai pulando de letra em letra a cada volta do loop. Toda vez que ele mudar de letra irá retornar dois valores, o índice e o valor daquele caractere.  

O ``indice`` indicará a localização do caractere na string. Começando do zero até finalizar toda a extensão da variável. O espaço está na localização 6, lembrando que começamos a contar sempre do zero.
*Muitas pessoas chamam o índice de ``i``*. 

Já o valor, value, irá receber a informação do valor daquele caractere.
*Podemos chama-lo apenas de ``v``*. 

Juntando as duas informações ``i`` e ``v``, conseguimos indicar a localização e o valor das letras: ``fmt.Printf("indice: %v, valor: %v", i, v)``.  

Se não precisarmos de um desses valores, podemos apenas ignora-lo utilizando o underline ``_``.

```golang

serie := "modern family" 

for _, valor := range serie {...}
//Estou ignorando o índice
```

Para exibir as letras como caracteres, podemos converter novamente para strings.

```golang

serie := "modern family" 

for i, v := range serie {
  
    fmt.Printf("índice: %v - valor: %v -  letra: %s\n", i, v, string(v))

}
/*
resultado:
índice: 0 - valor: 109 - letra: m
índice: 1 - valor: 111 - letra: o 
índice: 2 - valor: 100 - letra: d
índice: 3 - valor: 101 - letra: e
índice: 4 - valor: 114 - letra: r
índice: 5 - valor: 110 - letra: n
índice: 6 - valor: 32 - letra:
índice: 7 - valor: 102 - letra: f
índice: 8 - valor: 97 - letra: a
índice: 9 - valor: 109 - letra: m
índice: 10 - valor: 105 - letra: i
índice: 11 - valor: 108 - letra: l
índice: 12 - valor: 121 - letra: y
*/
```

Muitas das coisas que fazemos com o for range também podem ser feitas com o for normal, esse exemplo é uma delas.

Apenas precisamos conhecer a funcionalidade do **``len``**. Length que dizer comprimento, extensão. Ele pegará o comprimento da minha string e assim poderemos fazer o for normal de acordo com a extensão, assim como o for range. 

```golang
serie := "modern family" 

for i := 0; i < len(serie); i++ {//enquanto i for menor que a extensão da string
  
    fmt.Printf("índice: %v - valor: %v -  letra: %s\n", i, serie[i], string(serie[i]))

}
```

Outra diferença é esse tal de ``serie[i]``. O for normal não irá pular de letra em letra automaticamente igual ao range. Então temos que indicar de alguma forma que a cada loop iremos mudar de letra. Por isso utilizamos o ``serie[i]``.

Essa estrutura é muito utilizada em arrays e slices. Colocamos o nome da variável e o índice que queremos fica dentro dos colchetes. Como o ``i`` começa do zero e será incrementado a cada volta do loop, ele será nosso índice. 

O resultado dos dois ``for`` será exatamente o mesmo, **mas nem sempre será assim**. Vamos ver o que acontece se um caractere ocupar mais de um byte. 

 ```golang

sdds := "São João" 

for i, v := range sdds{
  
    fmt.Printf("índice: %v - valor: %v -  letra: %s\n", i, v, string(v))

}
/*
resultado:
índice: 0 - valor: 83 - letra: S
índice: 1* - valor: 227 - letra: ã
índice: 3* - valor: 111 - letra: o
índice: 4 - valor: 32 - letra:
índice: 5 - valor: 74 - letra: J
índice: 6 - valor: 111 - letra: o
índice: 7* - valor: 227 - letra: ã
índice: 9* - valor: 111 - letra: o
*/
```
No ``for range`` não aconteceu nenhuma mudança. Mas percebam que os índices estão pulando alguns números, ele foi de 1 para 3 e de 7 para 9. 

Vamos ver no ``for``:

```golang
sdds:= "São João" 

for i := 0; i < len(sdds); i++ {
  
    fmt.Printf("índice: %v - valor: %v -  letra: %s\n", i, sdds[i], string(sdds[i]))

}

/*
Resultado:
índice: 0 - valor: 83 - letra: S
índice: 1 - valor: 195 - letra: Ã*
índice: 2 - valor: 163 - letra: £*
índice: 3 - valor: 111 - letra: o
índice: 4 - valor: 32 - letra:
índice: 5 - valor: 74 - letra: J
índice: 6 - valor: 111 - letra: o
índice: 7 - valor: 195 - letra: Ã*
índice: 8 - valor: 163 - letra: £*
índice: 9 - valor: 111 - letra: o
*/
``` 
Os índices não pularam nenhum número, mas em compensação alguns caracteres estranhos apareceram. 

Isso aconteceu pois existem letras acentuadas, elas ocupam 2 bytes, diferente das outras. **O ``for range`` percorrer caractere por caractere (``int32``), não importando quantos bytes eles ocupam. Já o ``for`` irá de byte por byte (``uint8``)**, então se uma letra ocupar mais de um byte, o for irá mostrar. 

Essa é uma diferença sutil, mas as vezes o resultado não sai como o esperado e não sabemos o motivo.  

Hoje conhecemos o ``for range`` e trabalhamos um pouco mais com o ``for``, espero que tenham entendido e procurem exercitar e experimentar mais os dois.

 Se quiserem me acompanhar nos estudos: [É só clicar aqui](https://youtu.be/WiGU_ZB-u0w) e ser feliz.

**A missão de hoje foi realizada com sucesso, até amanhã**. 

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