¿Existe foreach en Go? Tutorial paso a paso con ejemplos
\n\nSi vienes a Go desde Python, JavaScript o PHP, seguramente estás acostumbrado al conciso foreach para recorrer colecciones. Y entonces escribes tu primer bucle en Go y te preguntas: «¿Y dónde está mi querido foreach? ¿Acaso Go no lo tiene?»
Spoiler: la palabra clave directa foreach realmente no existe en Go. Pero hay algo mucho más flexible y potente: la construcción for range. En este tutorial analizaremos cómo funciona la iteración en Go, mostraremos ejemplos reales de código y lo compararemos con el conocido foreach de otros lenguajes.
¿Por qué Go no tiene foreach y para qué sirve range?
\n\nGo es un lenguaje minimalista. Sus creadores evitaron intencionadamente la duplicación de construcciones sintácticas. En lugar de agregar una palabra clave separada foreach, ampliaron las capacidades del bucle for existente. Así nació for range, una herramienta universal para recorrer arrays, slices, maps, strings e incluso channels.
Si buscas un análogo exacto de foreach en Go, aquí lo tienes: for range.
Sintaxis de for range: explicación sencilla
\n\nLa estructura básica es la siguiente:
\n\nfor index, value := range collection {\n // cuerpo del bucle\n}\n\nDonde:
\n- \n
index— el índice del elemento (para arrays y slices) o la clave (para maps). \n value— una copia del valor del elemento. \n collection— tu colección (slice, array, map, string o channel). \n
Un punto importante: value es siempre una copia del elemento. Si modificas value dentro del bucle, el elemento original no cambiará. Para modificar los originales, debes acceder a través del índice.
Ejemplo 1: Recorrer un slice — análogo de foreach en Go
\n\nEmpecemos con el caso más común: recorrer los elementos de un slice:
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n fruits := []string{"manzana", "plátano", "cereza", "melón"}\n\n fmt.Println("Recorrido del slice (análogo a foreach):")\n for index, fruit := range fruits {\n fmt.Printf("Índice %d: %s\\n", index, fruit)\n }\n}\n\nSalida:
\nRecorrido del slice (análogo a foreach):\nÍndice 0: manzana\nÍndice 1: plátano\nÍndice 2: cereza\nÍndice 3: melón\n\nSi solo necesitas el índice (por ejemplo, para modificar elementos), puedes omitir el valor:
\n\nfor i := range fruits {\n fruits[i] = "fruta: " + fruits[i]\n}\n\nY si solo necesitas los valores, usa el guion bajo _:
for _, fruit := range fruits {\n fmt.Println(fruit)\n}\n\nEjemplo 2: Recorrer un map — foreach clásico
\n\nEn Go no hay una forma más elegante de recorrer maps que con for range:
package main\n\nimport "fmt"\n\nfunc main() {\n ages := map[string]int{\n "Ana": 25,\n "Borja": 30,\n "Víctor": 35,\n }\n\n fmt.Println("Recorrido del map (foreach):")\n for name, age := range ages {\n fmt.Printf("%s: %d años\\n", name, age)\n }\n}\n\nEl orden de recorrido de un map en Go no está garantizado. Si necesitas un orden estable, recoge las claves en un slice y ordénalo.
\n\nEjemplo 3: Recorrer un string — iteración carácter por carácter
\n\nA diferencia de muchos lenguajes, for range en Go itera sobre runas (caracteres Unicode), no sobre bytes:
package main\n\nimport "fmt"\n\nfunc main() {\n text := "¡Hola, Go!"\n\n fmt.Println("Recorrido del string por caracteres:")\n for i, r := range text {\n fmt.Printf("Posición %d: carácter '%c' (código %U)\\n", i, r, r)\n }\n}\n\nTen en cuenta: el índice i indica el byte inicial de la runa, no el número de orden del carácter. Para strings con un solo byte