Go não tem a palavra-chave while. Escreva for seguido de uma condição, e você tem um laço while:
A condição é verificada antes de cada iteração, então se ela for falsa logo no início o corpo nunca executa. É idêntico a while (balance < 2000) em C, Java ou JavaScript, sem os parênteses e sem a palavra-chave. Os criadores do Go escolheram uma única palavra-chave para todos os formatos de laço; veja a página do laço for para as quatro formas.
while(true): o laço infinito
Tire a condição por completo e o laço executa até que algo dentro dele o encerre:
for { } é a forma idiomática. for true { } também compila, mas parece código de quem veio de outra linguagem.
Quatro coisas encerram um laço infinito: break (sai do laço), return (sai da função), um panic e os.Exit. Um programa cujo main fica em um for {} sem nenhuma delas roda até ser morto, o que é exatamente o certo para um servidor ou worker.
do-while
Um do-while executa o corpo uma vez antes de verificar a condição. Go não tem sintaxe própria para isso. Coloque a verificação no fim de um laço infinito:
O corpo executa pelo menos uma vez, aconteça o que acontecer, que é a propriedade que define o do-while. A fonte aleatória usa uma semente fixa para que a saída seja a mesma em toda execução; use rand.IntN sem uma fonte com semente para aleatoriedade de verdade.
Uma segunda forma mantém a condição no cabeçalho forçando a primeira passada:
for first := true; first || condition(); first = false {
// body
}
Funciona, mas o laço infinito com um break no final é mais fácil de ler, e é o que a maior parte do código Go faz.
Lendo até acabar
O laço while mais comum em código Go real lê uma entrada até ela acabar. O bufio.Scanner foi feito para isso: Scan devolve false no fim da entrada ou em um erro, então ele é a condição do laço:
Troque strings.NewReader(input) por os.Stdin e o mesmo laço lê a entrada do usuário linha por linha. Verifique scanner.Err() depois do laço: Scan devolver false não diz se a entrada terminou normalmente ou falhou.
break e continue
Os dois funcionam em todas as formas de for:
Em um laço só com condição, o continue pula direto para a condição. Isso facilita um bug sutil: se o contador é atualizado no fim do corpo, um continue acima dele pula a atualização e o laço nunca termina. Atualize o contador no começo, como acima, ou use um for de três cláusulas, cuja instrução post executa mesmo depois de um continue.
Esperando por algo
Um laço que espera por uma condição deve bloquear ou dormir, não girar em vão:
// Wrong: burns a CPU core while waiting
for !ready {
}
// Better: poll with a delay
for !isReady() {
time.Sleep(100 * time.Millisecond)
}
Consultar repetidamente uma variável comum que outra goroutine escreve também é uma data race. Entre goroutines, espere em um channel, em um sync.WaitGroup ou em um sync.Cond, ou use select com um timer. Para laços de nova tentativa com limite, prefira um for contado, para que o laço não possa rodar para sempre:
for attempt := 1; attempt <= 5; attempt++ {
if err := connect(); err == nil {
break
}
time.Sleep(time.Duration(attempt) * 200 * time.Millisecond)
}
Erros comuns
- Esquecer de mudar a variável da condição.
for i < 10 { fmt.Println(i) }nunca termina. Todo laço while precisa de algo no corpo que o leve em direção à saída. - Escrever
while.while x < 5 {}dásyntax error: unexpected name x at end of statement, porquewhilenão é palavra-chave; o compilador o lê como um nome comum. - Parênteses por hábito.
for (x < 5) {}compila, e ogofmtremove os parênteses. - Declarar a variável no laço.
for n := 10; n > 0 {}é erro de sintaxe; um laço com cláusula de inicialização precisa das três cláusulas. Declarenantes do laço ou escreva a forma completa de três cláusulas.
Perguntas frequentes
Go tem laço while?
Não como palavra-chave. Go usa for para todo laço, e um for só com condição é exatamente um laço while:
for count < 10 {
count++
}
A condição é verificada antes de cada iteração, igual a while (count < 10) em C ou Java.
Como escrever while(true) em Go?
Escreva for sem nada depois: for { ... }. Ele repete até que um break, return, panic ou os.Exit o encerre. for true { ... } também compila, mas for { } é a forma idiomática.
Como escrever um laço do-while em Go?
Use um laço infinito e coloque a verificação da condição no fim do corpo:
for {
// body runs at least once
if !condition {
break
}
}
O corpo sempre executa uma vez antes de a condição ser testada, que é o que do-while significa.