Evaluation of range expressions

June 11, 2024

For statements with range clause

The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.

The first part of this seems pretty self-evident, as it follows the same pattern as a for statement with a for clause: The expression needs to be evaluated once before the loop executes.

But this one has an exception. Let’s look at that to make sure we understand it.

First “if at most one iteration variable is present”. This means our code looks something like this:

for i := range x {

This form works for any of the supported types, but the next condition limits us more: “and len(x) is constant”.

len(x) is only constant in a few cases: When x is an array, or a string constant or literal.

But why? Why is it okay to not execute the range expression in such a case?

for x := range "Hello, 世界" {

Because we never need the result of that evaluation! All we (the compiler/runtime) care about in this case is the number of elements, since that’s what the first and only loop variable represents. And it’s a constant, so it’s known at compilation time. This tells us that the compiler is actually optimizing our code to be simpler, in effect turning the above for loop into:

for x := range len("Hello, 世界") {

which can in effect be further simplified to:

for x := range 11 {

Or this given a variable declaration var a [3]int, this:

for x := range a {

to this:

for x := range 3 {

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Iteration over strings

For statements with range clause … For a string value, the “range” clause iterates over the Unicode code points in the string starting at byte index 0. On successive iterations, the index value will be the index of the first byte of successive UTF-8-encoded code points in the string, and the second value, of type rune, will be the value of the corresponding code point. If the iteration encounters an invalid UTF-8 sequence, the second value will be 0xFFFD, the Unicode replacement character, and the next iteration will advance a single byte in the string.


Iteration over arrays and slices

For statements with range clause … For an array, pointer to array, or slice value a, the index iteration values are produced in increasing order, starting at element index 0. If at most one iteration variable is present, the range loop produces iteration values from 0 up to len(a)-1 and does not index into the array or slice itself. For a nil slice, the number of iterations is 0. From this above paragraph, we can be assured that ranging over an array, pointer to array, or slice, will operate in a defined order–from index 0, upward.


The types of iteration variables

For statements with range clause … For each iteration, iteration values are produced as follows if the respective iteration variables are present: Range expression 1st value 2nd value array or slice a [n]E, *[n]E, or []E index i int a[i] E string s string type index i int see below rune map m map[K]V key k K m[k] V channel c chan E, <-chan E element e E integer n integer type value i see below How do we read this table?

Get daily content like this in your inbox!

Subscribe