Hoje vamos falar um pouco mais sobre loops.
Vocês já ouviram valar sobre o for range
?
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
:
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 👇🏽:
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
.
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 _
.
serie := "modern family"
for _, valor := range serie {...}
//Estou ignorando o índice
Para exibir as letras como caracteres, podemos converter novamente para strings.
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.
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.
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
:
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 e ser feliz.
A missão de hoje foi realizada com sucesso, até amanhã.
Top comments (0)