Go: Range loops (for each loops) explained

Range statements iterate over slices, arrays, strings, maps or channels.


a := []string{"Foo", "Bar"}
for i, s := range a {
	fmt.Println(i, s)
0 Foo
1 Bar
  • The range expression, a, is evaluated once before beginning the loop.
  • The iteration values are assigned to the respective iteration variables, i and s, as in an assignment statement.
  • The second iteration variable is optional.
  • If a slice or map is nil, the number of iterations is 0.


For a string, the loop iterates over Unicode code points.

for i, ch := range "日本語" {
	fmt.Printf("%#U starts at byte position %d\n", ch, i)
U+65E5 '日' starts at byte position 0
U+672C '本' starts at byte position 3
U+8A9E '語' starts at byte position 6
  • The index is the first byte of a UTF-8-encoded code point; the second value, of type rune, is the value of the code point.
  • For an invalid UTF-8 sequence, the second value will be 0xFFFD, and the iteration will advance a single byte.


The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next.

m := map[string]int{
	"one":   1,
	"two":   2,
	"three": 3,
for k, v := range m {
	fmt.Println(k, v)
two 2
three 3
one 1
  • If a map entry that has not yet been reached is removed during iteration, this value will not be produced.
  • If a map entry is created during iteration, that entry may or may not be produced.


For channels, the iteration values are the successive values sent on the channel until closed.

ch := make(chan int)
go func() {
	ch <- 1
	ch <- 2
	ch <- 3
for n := range ch {
  • For a nil channel, the range loop blocks forever.


Be the first to comment!