bucle-for-go-unico-loop

Bucle for en Go: formas de iterar y bucles infinitos

  • 4 min

El bucle for en Go es la única estructura repetitiva del lenguaje. Con ella hacemos bucles clásicos, bucles tipo while y recorridos sobre colecciones.

Si vienes de C, Java o JavaScript, estarás acostumbrado a tener un arsenal de bucles: for, while, do-while, foreach… A veces usas uno, a veces otro, y a veces discutes con tu equipo sobre cuál es más eficiente.

En Go, los diseñadores cortaron por lo sano. Solo existe el bucle for.

No hace falta nada más. El bucle for puede comportarse como los bucles tradicionales simplemente omitiendo partes de su sintaxis.

Equivalencias con otros bucles

Todas las formas habituales se expresan con for:

Tipo de bucle tradicionalEn Go se escribe…Sintaxis
for (i=0; i<10; i++)for clásicofor i:=0; i<10; i++
while (condicion)for condicionalfor condicion
while (true)for infinitofor
do-whileNo existeSe simula con un for infinito + if break al final

El bucle for clásico

Esta es la forma que todos conocemos, idéntica a C o Java, pero sin paréntesis (igual que el if).

Sintaxis: for inicialización; condición; post { ... }

package main

import "fmt"

func main() {
    // Imprimir del 0 al 4
    for i := 0; i < 5; i++ {
        fmt.Println("Contador:", i)
    }
}
Copied!

Fíjate que la variable i se declara con := dentro del propio bucle. Esto significa que i solo existe dentro del bucle. Si intentas acceder a ella fuera, tendrás un error.

El for como while

En otros lenguajes usamos while cuando no sabemos cuántas iteraciones vamos a hacer, sino que dependemos de una condición booleana.

En Go, para conseguir esto, simplemente eliminamos la parte de inicialización y la de post. Dejamos solo la condición.

func main() {
    contador := 1

    // Esto equivale a: while (contador < 100)
    for contador < 100 {
        contador *= 2
        fmt.Println("El contador es ahora:", contador)
    }
}
Copied!

No hace falta una palabra clave nueva: si solo escribimos una condición, se comporta como un while.

El bucle infinito

¿Y si queremos un bucle que no termine nunca (o hasta que nosotros lo paremos manualmente)? Es el típico caso de un servidor web escuchando peticiones o un juego en su game loop.

En Go, eliminamos todo.

func main() {
    for {
        fmt.Println("¡Esto no para nunca!")

        // Necesitaremos un mecanismo para salir, o Ctrl+C
    }
}
Copied!

Esta es la forma canónica de hacer un while(true) en Go.

Control del bucle con break y continue

Al igual que en otros lenguajes, tenemos dos palabras clave para alterar el flujo normal dentro de un bucle:

  • break: Rompe el bucle inmediatamente y sale de él.
  • continue: Salta la iteración actual y pasa directamente a la siguiente (ejecutando el paso “post” si es un for clásico).

Ejemplo con break

Buscamos un número y queremos parar en cuanto lo encontremos.

for i := 0; i < 10; i++ {
    if i == 5 {
        fmt.Println("¡Encontrado el 5! Nos vamos.")
        break // Sale del for inmediatamente
    }
    fmt.Println("Buscando...", i)
}
Copied!

Ejemplo con continue

Queremos imprimir solo los números impares.

for i := 0; i < 5; i++ {
    if i%2 == 0 {
        continue // Es par, saltamos esta vuelta
    }
    fmt.Println("Impar:", i)
}
Copied!

Etiquetas en bucles anidados

Esto es algo que no se ve todos los días, pero es muy útil cuando trabajamos con algoritmos complejos. Si tienes un bucle dentro de otro bucle y quieres hacer un break que salga de ambos, puedes usar etiquetas.

func main() {
    // Definimos una etiqueta llamada "BuclePrincipal"
BuclePrincipal:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Println(i, j)
            if i == 1 && j == 1 {
                fmt.Println("¡Rompiendo todo!")
                break BuclePrincipal // Rompe el bucle externo etiquetado
            }
        }
    }
    fmt.Println("Fin del programa")
}
Copied!

Sin la etiqueta, el break solo saldría del bucle interno (j), y el externo (i) seguiría ejecutándose.

Iteración de colecciones

Aunque dedicaremos un artículo entero a las colecciones, es imposible hablar de for sin mencionar brevemente la cláusula range. Es el equivalente al foreach de C# o for..of de JS.

nombres := []string{"Luis", "Juan", "Ana"}

for indice, valor := range nombres {
    fmt.Printf("Posición %d: %s\n", indice, valor)
}
Copied!