Question
In Go, is there a foreach construct similar to other languages?
Can I iterate over a slice or array using a for loop, and if so, what is the idiomatic way to do it?
Short Answer
By the end of this page, you will understand how Go handles foreach-style iteration using for and range. You will see how to loop through slices and arrays, when to use indexes and values, and how this pattern is commonly used in real Go programs.
Concept
Go does not have a separate foreach keyword.
Instead, Go uses a single loop keyword: for. To write a foreach-style loop, you combine for with range.
This is the idiomatic Go way to iterate over collections such as:
- slices
- arrays
- maps
- strings
- channels
For slices and arrays, range gives you:
- the current index
- a copy of the current element value
Example:
numbers := []int{10, 20, 30}
for index, value := range numbers {
fmt.Println(index, value)
}
Why this matters:
- It is shorter and clearer than manually managing a counter.
- It reduces common indexing mistakes.
- It is the standard style used across Go codebases.
Go keeps the language small by reusing for for all looping needs instead of adding separate constructs like while and foreach.
Mental Model
Think of range as a helper that walks through a collection and hands you information for each step.
Imagine a row of labeled boxes:
- the label is the index
- the item inside is the value
When you write:
for i, v := range items {
// use i and v
}
Go is effectively saying:
- "Here is box
0and its value" - "Here is box
1and its value" - "Here is box
2and its value"
You can choose to use both the label and the item, or ignore one of them if you do not need it.
Syntax and Examples
Basic syntax
for index, value := range collection {
// use index and value
}
Iterate over a slice
package main
import "fmt"
func main() {
fruits := []string{"apple", "banana", "orange"}
for i, fruit := range fruits {
fmt.Println(i, fruit)
}
}
Output:
0 apple
1 banana
2 orange
Explanation:
iis the indexfruitis the value at that index
Ignore the index
If you only need the value, use _ for the index:
for _, fruit := range fruits {
fmt.Println(fruit)
}
Step by Step Execution
Consider this code:
package main
import "fmt"
func main() {
scores := []int{90, 85, 100}
for i, score := range scores {
fmt.Println("index:", i, "value:", score)
}
}
Step-by-step
scoresis created as a slice with three values:90,85, and100.- The
range scorespart starts iterating over the slice. - On the first loop:
ibecomes0scorebecomes90- Go prints
index: 0 value: 90
- On the second loop:
ibecomes
Real World Use Cases
Foreach-style iteration is used constantly in Go programs.
Common examples
Processing API results
for _, user := range users {
fmt.Println(user.Name)
}
Use this after decoding JSON into a slice of structs.
Validating input data
for _, email := range emails {
if email == "" {
fmt.Println("empty email found")
}
}
Useful when checking form input or imported CSV rows.
Building derived data
total := 0
for _, price := range prices {
total += price
}
Common in reports, analytics, and billing logic.
Updating elements by index
for i := range prices {
prices[i] = prices[i] * 2
}
This pattern matters when you need to modify the underlying slice.
Reading maps
for key, value := settings {
fmt.Println(key, value)
}
Real Codebase Usage
In real Go codebases, for range is often combined with simple control-flow patterns.
Common patterns
Validation loops
for _, item := range items {
if item.ID == 0 {
return fmt.Errorf("invalid item id")
}
}
Developers often stop early when bad data is found.
Filtering data
var activeUsers []User
for _, user := range users {
if user.Active {
activeUsers = append(activeUsers, user)
}
}
Go does not have built-in filter, so loops are the normal way.
Aggregation
count := 0
for _, order := range orders {
count += order.Quantity
}
Used for totals, summaries, and statistics.
Updating by index
for i := range users {
users[i].Active =
}
Common Mistakes
1. Expecting a foreach keyword
Broken expectation:
// This is not valid Go
foreach item in items {
fmt.Println(item)
}
Use this instead:
for _, item := range items {
fmt.Println(item)
}
2. Forgetting to use _ for unused values
Broken code:
for i, fruit := range fruits {
fmt.Println(fruit)
}
If i is never used, Go will report an error.
Correct version:
for _, fruit := range fruits {
fmt.Println(fruit)
}
3. Trying to modify the value variable and expecting the slice to change
Broken assumption:
numbers := []int{1, 2, 3}
for _, n := range numbers {
n = n *
}
fmt.Println(numbers)
Comparisons
| Approach | Syntax | Best for | Notes |
|---|---|---|---|
for _, v := range slice | Foreach-style | Reading values | Most idiomatic for simple iteration |
for i := range slice | Index-only | Modifying elements by index | Good when writing back to the slice |
for i, v := range slice | Index and value | Reading both position and item | Common and readable |
for i := 0; i < len(slice); i++ | Classic loop | Full control | Useful for custom stepping or paired indexing |
range vs classic for
Cheat Sheet
Foreach in Go
There is no foreach keyword in Go.
Use:
for _, value := range collection {
// use value
}
Common patterns
Index and value
for i, v := range items {
}
Value only
for _, v := range items {
}
Index only
for i := range items {
}
Classic loop
for i := 0; i < len(items); i++ {
}
Important rules
rangeworks with slices, arrays, maps, strings, and channels.- For slices and arrays,
rangereturns index and value. - The value variable is usually a copy.
FAQ
Is there a foreach loop in Go?
No. Go does not have a separate foreach keyword. The idiomatic equivalent is for ... range.
How do I loop over a slice in Go?
Use:
for _, v := range slice {
fmt.Println(v)
}
How do I get both index and value in a Go loop?
Use:
for i, v := range slice {
fmt.Println(i, v)
}
How do I change slice elements while looping?
Loop by index:
for i := range slice {
slice[i] = slice[i] * 2
}
Why does Go use _ in loops?
_ discards a value you do not need. This is useful because Go does not allow unused local variables.
Is range only for slices and arrays?
No. It also works with maps, strings, and channels.
Should I use or a classic loop?
Mini Project
Description
Build a small Go program that processes a list of product prices. This project demonstrates foreach-style iteration with for range, summing values, printing each item, and modifying a slice by index when needed.
Goal
Create a Go program that prints product prices, calculates the total, and then applies a discount by updating each price in the slice.
Requirements
- Create a slice of numeric prices.
- Use
for rangeto print each price. - Use
for rangeto calculate the total price. - Update each element in the slice to apply a discount.
- Print the updated slice after modification.
Keep learning
Related questions
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Concatenating Slices in Go with append
Learn how to concatenate two slices in Go using append and the ... operator, with examples, pitfalls, and practical usage.
Convert String to Integer in Go: Idiomatic Parsing with strconv.Atoi
Learn the idiomatic way to convert a string to an int in Go using strconv.Atoi, with examples, errors, and common mistakes.