How to Use `range` as a `foreach` in Go
Grace Collins
Solutions Engineer · Leapcell

Key Takeaways
- Go uses the
range
keyword to iterate over arrays, slices, maps, strings, and channels. - Although Go lacks a traditional
foreach
,range
serves the same purpose in an idiomatic way. - Custom
foreach
functions can be built using reflection for more dynamic scenarios.
In Go, there isn't a built-in foreach
loop like in some other languages. However, Go provides a powerful for
loop with the range
keyword that serves a similar purpose, allowing iteration over various data structures such as slices, arrays, maps, strings, and channels.
Iterating Over Slices and Arrays
When using range
with slices or arrays, it returns both the index and the value of each element.
package main import "fmt" func main() { numbers := []int{1, 2, 3, 4, 5} for index, value := range numbers { fmt.Printf("Index: %d, Value: %d\n", index, value) } }
If the index is not needed, it can be omitted using the blank identifier _
:
for _, value := range numbers { fmt.Println(value) }
Iterating Over Maps
Using range
with maps allows iteration over key-value pairs.
fruits := map[string]string{ "a": "apple", "b": "banana", } for key, value := range fruits { fmt.Printf("%s -> %s\n", key, value) }
Note that the iteration order over maps is not guaranteed and can vary between iterations.
Iterating Over Strings
When iterating over strings, range
returns the index and the rune (Unicode code point) at that position.
for index, char := range "GoLang" { fmt.Printf("Character at byte position %d: %c\n", index, char) }
This approach correctly handles multi-byte characters in UTF-8 encoded strings.
Iterating Over Channels
range
can also be used to receive values from a channel until it is closed.
ch := make(chan int) go func() { for i := 0; i < 5; i++ { ch <- i } close(ch) }() for val := range ch { fmt.Println(val) }
This pattern is useful for reading from channels without needing to check if the channel is closed explicitly.
Custom foreach
Implementations
While Go's range
covers most iteration needs, developers have created custom foreach
functions using reflection to apply a function to each element of a slice:
func ForEach(slice interface{}, fn func(interface{})) { v := reflect.ValueOf(slice) for i := 0; i < v.Len(); i++ { fn(v.Index(i).Interface()) } }
This approach allows applying a function to each element of a slice, regardless of its type.
Conclusion
Although Go doesn't have a traditional foreach
loop, the for
loop with the range
keyword provides a versatile and efficient way to iterate over various data structures. Understanding and utilizing range
effectively allows for clean and idiomatic Go code.
FAQs
No, Go doesn't have a foreach
keyword. Instead, it uses for
with range
to achieve similar functionality.
Yes, range
works with maps (to get key-value pairs) and with channels (to receive values until closed).
No, the iteration order over maps is randomized and not consistent between runs.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ