Como funciona for com range

Em Go, o for é uma ferramenta poderosa e flexível para realizar iterações. Dentro desse contexto, o uso do range é uma forma comum de percorrer slices, maps, strings, arrays e channels. Porém, entender como o range funciona internamente é essencial para evitar erros sutis, especialmente ao lidar com ponteiros.

Neste post, exploraremos os fundamentos do range em Go, destacaremos diferenças entre loopings com e sem range, e discutiremos erros comuns que surgem ao usar o range com ponteiros.

Avaliando a expressão

Sem range

O for em Go pode ser usado de forma simples e direta para controlar iterações com base em uma condição.

nums := []int{10, 20, 30}
for i := 0; i < len(nums); i++ {
	nums = append(nums, nums[i] + 10)
}

No exemplo acima, o desenvolvedor controla explicitamente as condições de início, fim e incremento. Porém há um pequeno problema.

Quando utilizamos essa “assinatura” para o for, a expressão que determina o fim do looping é avaliado a cada iteração. Como estamos fazendo um append, ou seja, adicionando novos itens ao slice, esse looping acaba sendo infinito.

Com range

O range abstrai esse controle e fornece uma maneira conveniente de iterar sobre slices, retornando sempre dois valores: o índice (ou chave, no caso de maps) e o valor correspondente.

Caso você não precise de um dos valores, como por exemplo o índice, é possível ignorá-lo utilizando o _.

nums := []int{10, 20, 30}
for _, v := range nums {
	nums = append(nums, v + 10)
}

Embora esse exemplo seja muito parecido com o anterior, a utilizando o range faz uma enorme diferença.

Isso por que loopings com range avaliam a expressão (item que vem logo após o comando) somente uma vez, antes de iniciar a iteração.

Outro ponto importante é que, por debaixo dos panos, o range cria uma cópia do slice, e itera sobre ele. Por isso, qualquer alteração no slice original não será refletido no slice do looping.

O exemplo abaixo exemplifica bem isso.

nums := []int{10, 20, 30}
for i, v := range nums {
	nums[i] = v * 10
	println(v)
}

// output será: 10, 20, 30

Conclusão

O range é uma funcionalidade incrível que facilita a iteração sobre coleções em Go. No entanto, é importante entender suas nuances para evitar erros comuns.

Ao manter esses conceitos em mente e aplicar boas práticas, você pode escrever código mais seguro e fácil de entender.

Até a próxima!


Faça parte da comunidade!

Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.

Livros Recomendados

Abaixo listei alguns dos melhores livros que já li sobre GO.

Deixe uma resposta