Variantes do Loop for & Semântica do range
O Go expressa todo loop com for, mas a forma que você escolhe muda o que você copia, o que você pode mutar e quando o loop para.
Busque em todas as páginas da documentação
O Go expressa todo loop com for, mas a forma que você escolhe muda o que você copia, o que você pode mutar e quando o loop para.
Esta página mapeia cada variante de for para as coleções e canais que você verá em código de produção.
O cabeçalho for de três partes cobre loops contados.
A forma apenas com condição age como while.
for range percorre slices, arrays, mapas, canais e strings com significado de índice/valor específico do tipo.
Canais bloqueiam até que um valor chegue ou o canal feche.
Mapas iteram em ordem aleatória.
Strings retornam deslocamentos de bytes e runas, não bytes diretamente.
Cartão de receita de referência rápida - pronto para copiar e colar.
package main
import "fmt"
func main() {
// Estilo C
for i := 0; i < 3; i++ {
fmt.Println("count", i)
}
// Estilo while
n := 3
for n > 0 {
n--
}
// range slice
for i, v := range []int{10, 20} {
fmt.Println(i, v)
}
}Quando usar isso:
for de três partes quando precisar de um contador de índice com uma condição final clara.for apenas com condição para loops de eventos, novas tentativas e bombas de canal (for { select { ... } }).for range para iteração idiomática sobre coleções e canais abertos.for range em vez de alternativas 1..n via slices ou for i := 0; i < n; i++ - Go não tem operador de intervalo inclusivo.package main
import (
"fmt"
"time"
)
func main() {
// Slice: mutar por índice
nums := []int{1, 2, 3}
for i := range nums {
nums[i] *= 2
}
fmt.Println("slice", nums)
// Map: chaves e valores (ordem varia a cada execução)
m := map[string]int{"a": 1, "b": 2}
for k, v := range m {
fmt.Println("map", k, v)
}
// Canal: receber até fechar
ch := make(chan int, 2)
ch <- 1
ch <- 2
close(ch)
for v := range ch {
fmt.Println("chan", v)
}
// String: índice de byte e runa
for i, r := range "Go🙂" {
fmt.Printf("string i=%d r=%U\n", i, r)
}
// Loop infinito com break por timeout
deadline := time.Now().Add(50 * time.Millisecond)
for {
if time.Now().After(deadline) {
break
}
}
fmt.Println("done")
}O que isso demonstra:
for range em um canal termina quando o canal é fechado e todos os valores em buffer são recebidos.range de string decodifica runas UTF-8; o índice salta pela largura em bytes para caracteres multibyte.break, return ou select.for cria um escopo de bloco; a variável de inicialização em um loop de três partes tem escopo para a instrução for.range avalia a coleção uma vez; para arrays/slices, ele copia o cabeçalho, não os elementos do array de suporte.for range bloqueia até que um valor esteja pronto; o padrão de valor zero mais ok é implícito na forma de range.len(s) é o comprimento em bytes, que difere da contagem de runas.| Tipo | Índice (1º valor) | Valor (2º valor) | Notas |
|---|---|---|---|
| Slice / array | índice int | cópia do elemento | mutar com s[i], não v |
| Map | cópia da chave | cópia do valor | ordem aleatória |
| Canal | (nenhum) | elemento recebido | termina após fechar + esvaziar |
| String | deslocamento de byte | rune (int32) | o deslocamento avança pela largura UTF-8 |
| Forma | Sintaxe | Uso Típico |
|---|---|---|
| Três partes | for i := 0; i < n; i++ | loops contados |
| Apenas condição | for cond | estilo while, ler até EOF |
| Infinito | for { } | servidores, loops select |
| Range | for k, v := range x | coleções, canais, strings |
// Omita valor ou índice com o identificador em branco
for _, v := range items { _ = v }
for i := range items { _ = i }
// range sobre array copia elementos para a forma de valor em arrays grandes - use índice
var big [10000]byte
for i := range big {
big[i] = 1
}for _, v := range s { v = 1 } atualiza uma cópia. Correção: use índice: for i := range s { s[i] = 1 }.for range ch bloqueia para sempre. Correção: feche do lado do remetente ou use select com ctx.Done().len("é") são 2 bytes em UTF-8. Correção: use range ou utf8.RuneCountInString.<= quando < era a intenção. Correção: prefira os idiomas for i := 0; i < len(s); i++.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
for range | Iteração idiomática | Você precisa de iteração reversa sem matemática de índice extra |
Índice for i := 0; ... | Precisa do elemento anterior/seguinte por índice | Um loop de range simples é suficiente |
slices.Backward / índice manual | Caminhada reversa | O range para frente é suficiente |
for { select } | Multiplexar canais e timers | Caminhada de coleção única |
| Iteradores da biblioteca padrão (Go 1.23+) | Sequências personalizadas com yield | Caminhadas simples de slice/map |
Não - for condition { } é a forma while.
A palavra-chave é sempre for.
Sim - ambos são no-ops com zero iterações.
Um mapa nil ainda é ilegível para atribuição sem make.
O Go randomiza o início da iteração do mapa para evitar dependência da ordem.
Ordene as chaves quando precisar de saída determinística.
Após o canal ser fechado e todos os valores em buffer serem recebidos.
Um canal aberto bloqueia para sempre na próxima recepção.
O valor é uma cópia - caro para structs grandes.
Use índice ou slice de ponteiro []*T quando a profilaxia mostrar custo de cópia.
Use for i := 0; i < n; i++.
Não há for i := range n em Go mais antigo; Go 1.22+ permite for i := range n quando n é um inteiro.
Ele itera i de 0 a n-1 quando n é um tipo de inteiro não negativo.
Útil para loops contados sem inicialização/pós-processamento manual.
Sim - deletar a chave atual é seguro.
Deletar outras chaves durante a iteração segue as semânticas do mapa; mantenha a lógica simples.
Use break em um rótulo ou return da função.
break sozinho sai do select, não do for circundante.
Ele decodifica UTF-8, o que custa mais do que varreduras brutas de bytes.
Para dados apenas ASCII, acesse os bytes diretamente com verificações de limites.
for e rangeVersões de Stack: Esta página foi escrita para Go 1.26.x (padrão Green Tea GC, go fix modernizers - verifique o patch na compilação), chi (última - verifique na compilação), gin (última - verifique na compilação), echo (última - verifique na compilação), google.golang.org/grpc (última - verifique na compilação), sigs.k8s.io/controller-runtime (última - verifique na compilação), kubebuilder (última - verifique na compilação), tinygo (última - verifique os alvos de placa na compilação), wazero (última - verifique na compilação) e golangci-lint (última - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026