Go 1.22 Loop Improvements for Iterating Over Integers: Range Over N Syntax
Go 1.22 introduced the for i := range n syntax, allowing developers to iterate from 0 to n-1 without writing the traditional three-component for loop boilerplate.
Go 1.22 delivers a significant ergonomic improvement for simple counting loops by extending the range clause to support integer expressions. According to the JetBrains/go-modern-guidelines repository, this modernization eliminates verbose index declarations while maintaining full compiler optimizations for traversing collections by length or performing fixed iterations.
The New Range Over Integer Syntax
Go 1.22 permits range to appear with a single integer expression n, creating an implicit loop variable that counts from 0 to n-1. According to the range_over_int guideline defined in internal/guidelines/guidelines.json (lines 579-594), the compiler automatically manages the iteration bounds, removing the need for manual index arithmetic.
Before (pre‑Go 1.22 classic form):
for i := 0; i < len(items); i++ {
process(items[i])
}
After (Go 1.22+ range syntax):
for i := range len(items) {
process(items[i])
}
Key Advantages of the Modern Syntax
Enhanced Code Readability
The concise form immediately signals the intent: "iterate n times" or "process each index of a collection." The internal/guidelines/guidelines.json specification emphasizes that range makes the loop's purpose explicit compared to the ceremonial initialization, condition, and post-statement of traditional loops.
Compile-Time Safety Guarantees
Because the compiler controls the iteration variable i, the range-based form prevents off-by-one errors that commonly occur with manual boundary checks. If the bound expression changes during execution, Go's runtime ensures the loop adapts correctly, eliminating a common source of logical errors in hand-written i < n patterns.
Performance Optimizations
The compiler generates tighter machine code when it recognizes the range over integer pattern. By knowing the loop bounds ahead of time, the compiler avoids repeated boundary comparisons and can apply unrolling or other optimizations that might be obstructed by the general-purpose nature of classic for loops.
When to Retain the Traditional For Loop
Despite the new syntax, the classic for i := 0; i < n; i++ structure remains necessary for scenarios requiring:
- Non-zero starting indices: Begin iteration from values other than 0
- Custom step sizes: Increment by values other than 1 (e.g.,
i += 2) - Dynamic boundary modifications: Adjusting the upper bound within the loop body based on runtime conditions
Implementation in JetBrains Go Modern Guidelines
The JetBrains/go-modern-guidelines repository codifies this pattern in internal/guidelines/guidelines.json under the range_over_int entry. The internal/guidelines/guidelines.go file loads and exposes these recommendations, enabling IDE integrations to suggest the modern syntax when detecting eligible three-part loops. The guideline specifically targets loops where the sole purpose is zero-based counting, as implemented in the JSON configuration spanning lines 579-594.
Summary
- Go 1.22 introduces
for i := range nas a concise alternative tofor i := 0; i < n; i++ - The syntax improves readability and prevents off-by-one errors through compiler-managed bounds
- The JetBrains/go-modern-guidelines repository defines this pattern as the range_over_int guideline in
internal/guidelines/guidelines.json - Classic three-part loops remain necessary for non-zero starts, custom steps, or mutating bounds
Frequently Asked Questions
What is the exact syntax for ranging over integers in Go 1.22?
Use for i := range n where n is any integer expression. The loop variable i automatically takes values from 0 to n-1. This syntax only works in Go 1.22 and later versions; earlier compilers will reject the integer range clause.
Does the range over integer syntax work with negative numbers?
No. If n is negative or zero, the loop simply executes zero iterations. The range clause expects the integer to represent a count, and negative values are treated as equivalent to zero, preventing runtime panics from invalid bounds.
Can I still access the index variable inside the loop body?
Yes. The loop variable i behaves exactly like a traditional index variable, remaining in scope throughout the loop body. You can use it for indexing slices, accessing parallel arrays, or tracking iteration count without any behavioral differences from manual index management.
How do the JetBrains Go Modern Guidelines enforce this pattern?
The guidelines repository stores the range_over_int rule in internal/guidelines/guidelines.json, which defines when to prefer range over classic for loops. The internal/guidelines/guidelines.go loader parses this configuration, allowing JetBrains IDEs like GoLand to highlight refactor opportunities and suggest the modern syntax automatically during code inspections.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →