Is there foreach in Go? Step-by-step guide for beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Is there foreach in Go? Step-by-step tutorial with examples

\n\n

If you came to Go from Python, JavaScript, or PHP, you are probably used to the concise foreach for iterating over collections. And so you write your first loop in Go and ask yourself: "Where is my beloved foreach? Is it really not in Go?"

\n\n

Spoiler: there is indeed no direct foreach keyword in Go. But there is something much more flexible and powerful — the for range construct. In this tutorial, we will break down how iteration works in Go, show real code examples, and compare it with the familiar foreach from other languages.

\n\n

Why is there no foreach in Go and why is range needed?

\n\n

Go is a minimalist language. Its creators intentionally avoided duplicating syntactic constructs. Instead of adding a separate foreach keyword, they extended the capabilities of the existing for loop. Thus for range was born — a universal tool for iterating over arrays, slices, maps, strings, and even channels.

\n\n

If you are looking for an exact analog of foreach in Go, here it is — for range.

\n\n

For range syntax: a simple breakdown

\n\n

The basic structure looks like this:

\n\n
for index, value := range collection {\n    // loop body\n}
\n\n

Where:

\n
    \n
  • index — the index of the element (for arrays and slices) or the key (for maps).
  • \n
  • value — a copy of the element's value.
  • \n
  • collection — your collection (slice, array, map, string, or channel).
  • \n
\n\n

Important point: value is always a copy of the element. If you change value inside the loop, the original element will not change. To modify the originals, you need to access them via the index.

\n\n

Example 1: Iterating over a slice — analog of foreach in Go

\n\n

Let's start with the most common case — iterating over slice elements:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    fruits := []string{"apple", "banana", "cherry", "melon"}\n\n    fmt.Println("Iterating over a slice (foreach analog):")\n    for index, fruit := range fruits {\n        fmt.Printf("Index %d: %s\\n", index, fruit)\n    }\n}
\n\n

Output:

\n
Iterating over a slice (foreach analog):\nIndex 0: apple\nIndex 1: banana\nIndex 2: cherry\nIndex 3: melon
\n\n

If you only need the index (for example, to modify elements), you can omit the value:

\n\n
for i := range fruits {\n    fruits[i] = "fruit: " + fruits[i]\n}
\n\n

And if you only need the values — use the underscore _:

\n\n
for _, fruit := range fruits {\n    fmt.Println(fruit)\n}
\n\n

Example 2: Iterating over a map — classic foreach

\n\n

In Go, there is no more elegant way to iterate over maps than for range:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    ages := map[string]int{\n        "Anna": 25,\n        "Boris": 30,\n        "Victor": 35,\n    }\n\n    fmt.Println("Iterating over a map (foreach):")\n    for name, age := range ages {\n        fmt.Printf("%s: %d years old\\n", name, age)\n    }\n}
\n\n

The iteration order over a map in Go is not guaranteed. If you need a stable order, collect the keys into a slice and sort it.

\n\n

Example 3: Iterating over a string — character-by-character iteration

\n\n

Unlike many languages, for range in Go iterates over runes (unicode characters), not bytes:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    text := "Hello, Go!"\n\n    fmt.Println("Iterating over a string by characters:")\n    for i, r := range text {\n        fmt.Printf("Position %d: character '%c' (code %U)\\n", i, r, r)\n    }\n}
\n\n

Note: the index i indicates the starting byte of the rune, not the ordinal number of the character. For single-byte

Blogs

Book Recommendations