← Back to Go Course | Chapter 3: Control Flow | Lesson 7 of 7

The range Keyword

range is Go's way of saying 'go through every item in this collection, one by one, and tell me where each one is'.
Syntax
go
for index, value := range collection {
    // body
}

for key, value := range mapValue {
    // body
}

Ranging Over a Slice

range on a slice or array gives you both the index and the value at each step, letting you avoid manually managing an index variable and bounds checks.

Example: Ranging Over a Slice

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create fruits and infer the type
	fruits := []string{"apple", "banana", "cherry"}
	// Loop over fruits, getting each index and value
	for i, fruit := range fruits {
		// Print the values followed by a newline
		fmt.Println(i, fruit)
	}
}

Ignoring the Index or Value

If you only care about the value and not the index (or vice versa), the blank identifier _ discards the part you don't need, satisfying Go's rule that every declared variable must be used.

Note: Go's compiler rejects a declared-but-unused variable, so _ is essential when you only need one of the two range values.

Example: Ignoring the Index or Value

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create fruits and infer the type
	fruits := []string{"apple", "banana", "cherry"}
	// Loop over fruits; the blank identifier _ ignores the index
	for _, fruit := range fruits {
		// Print the values followed by a newline
		fmt.Println("fruit:", fruit)
	}
}

Ranging Over a Map

range on a map yields each key-value pair, but the order of iteration is deliberately randomized by the Go runtime every time the program runs, which prevents code from accidentally depending on a specific order.

Note: Map iteration order is intentionally randomized by Go each run -- never rely on it being consistent.

Example: Ranging Over a Map

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create ages and infer the type
	ages := map[string]int{"Amit": 30, "Sara": 25}
	// Short declaration: create total and infer the type
	total := 0
	// Loop over ages; the blank identifier _ ignores the index
	for _, age := range ages {
		total += age
	}
	// Print the values followed by a newline
	fmt.Println("total age:", total)
}

Ranging Over a String

range on a string decodes it as UTF-8, yielding the byte index and the rune (full character) at that position -- correctly handling multi-byte characters, unlike a plain byte-index loop.

Example: Ranging Over a String

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	for i, r := range "Go!" {
		// Print using a format string
		fmt.Printf("%d: %c\n", i, r)
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Assuming the range loop variable is a fresh variable each iteration in older Go versions -- pre-1.22 it was reused, causing common closure-capture bugs.
  2. Ignoring the index/key that range provides when only the value is needed, instead of using the blank identifier _ to discard it.
  3. Modifying a slice's length while ranging over it, which does not change how many iterations the already-started range performs.
Chapter Summary
  • range iterates over arrays, slices, strings, maps, and channels, adapting its output to each type.
  • For slices/arrays, range yields index and value; for maps, key and value; for strings, byte index and rune.
  • Use the blank identifier _ to ignore a value you don't need from range.
  • Since Go 1.22, each range iteration gets its own fresh loop variable, avoiding an old class of closure bugs.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.