Go no tiene la palabra clave while. Escribe for seguido de una condición y ya tienes un bucle while:
La condición se comprueba antes de cada iteración, así que si es falsa desde el principio el cuerpo nunca se ejecuta. Es idéntico a while (balance < 2000) en C, Java o JavaScript, sin los paréntesis ni la palabra clave. Los diseñadores de Go eligieron una sola palabra clave para todas las formas de bucle; consulta la página del bucle for para ver las cuatro.
while(true): el bucle infinito
Si omites la condición por completo, el bucle se ejecuta hasta que algo dentro lo termina:
for { } es la forma idiomática. for true { } también compila, pero se lee como si el autor viniera de otro lenguaje.
Cuatro cosas terminan un bucle infinito: break (sale del bucle), return (sale de la función), un panic y os.Exit. Un programa cuyo main se queda en for {} sin ninguna de ellas se ejecuta hasta que alguien lo mata, que es justo lo correcto para un servidor o un worker.
do-while
Un do-while ejecuta el cuerpo una vez antes de comprobar la condición. Go no tiene una sintaxis propia para ello. Pon la comprobación al final de un bucle infinito:
El cuerpo se ejecuta al menos una vez pase lo que pase, que es la propiedad que define un do-while. La fuente aleatoria usa una semilla fija para que la salida sea la misma en cada ejecución; usa rand.IntN sin una fuente con semilla para tener aleatoriedad real.
Una segunda forma mantiene la condición en la cabecera forzando la primera pasada:
for first := true; first || condition(); first = false {
// body
}
Funciona, pero el bucle infinito con un break al final se lee mejor, y es lo que hace la mayor parte del código Go.
Leer hasta terminar
El bucle while más común en código Go real lee la entrada hasta que se acaba. bufio.Scanner está pensado para eso: Scan devuelve false al final de la entrada o ante un error, así que sirve como condición del bucle:
Cambia strings.NewReader(input) por os.Stdin y el mismo bucle lee la entrada del usuario línea a línea. Comprueba scanner.Err() después del bucle: que Scan devuelva false no te dice si la entrada terminó con normalidad o falló.
break y continue
Los dos funcionan en todas las formas de for:
En un bucle con solo condición, continue salta directamente a la condición. Eso facilita un bug sutil: si el contador se actualiza al final del cuerpo, un continue situado antes se salta la actualización y el bucle nunca termina. Actualiza el contador al principio, como arriba, o usa un for de tres partes, cuya sentencia post se ejecuta incluso después de continue.
Esperar a que ocurra algo
Un bucle que espera una condición debería bloquearse o dormir, no girar en vacío:
// Wrong: burns a CPU core while waiting
for !ready {
}
// Better: poll with a delay
for !isReady() {
time.Sleep(100 * time.Millisecond)
}
Consultar una variable normal que escribe otra goroutine es además una carrera de datos. Entre goroutines, espera en un channel, un sync.WaitGroup o un sync.Cond, o usa select con un temporizador. Para bucles de reintento con límite, prefiere un for con contador para que el bucle no pueda ejecutarse para siempre:
for attempt := 1; attempt <= 5; attempt++ {
if err := connect(); err == nil {
break
}
time.Sleep(time.Duration(attempt) * 200 * time.Millisecond)
}
Errores comunes
- Olvidar cambiar la variable de la condición.
for i < 10 { fmt.Println(i) }nunca termina. Todo bucle while necesita algo en el cuerpo que lo acerque a la salida. - Escribir
while.while x < 5 {}dasyntax error: unexpected name x at end of statement, porquewhileno es una palabra clave; el compilador lo lee como un nombre normal. - Paréntesis por costumbre.
for (x < 5) {}compila, ygofmtquita los paréntesis. - Declarar la variable en el bucle.
for n := 10; n > 0 {}es un error de sintaxis; un bucle con cláusula de inicio necesita las tres partes. Declaranantes del bucle, o escribe la forma completa de tres partes.
Preguntas frecuentes
¿Tiene Go un bucle while?
No como palabra clave. Go usa for para todos los bucles, y un for con solo una condición es exactamente un bucle while:
for count < 10 {
count++
}
La condición se comprueba antes de cada iteración, igual que while (count < 10) en C o Java.
¿Cómo escribo while(true) en Go?
Escribe for sin nada detrás: for { ... }. Se repite hasta que lo termina un break, un return, un panic o os.Exit. for true { ... } también compila, pero for { } es la forma idiomática.
¿Cómo escribo un bucle do-while en Go?
Usa un bucle infinito y pon la comprobación de la condición al final del cuerpo:
for {
// body runs at least once
if !condition {
break
}
}
El cuerpo siempre se ejecuta una vez antes de comprobar la condición, que es lo que significa do-while.