Terminating for loops

April 3, 2024

Terminating statements

  1. A “for” statement in which:

    • there are no “break” statements referring to the “for” statement, and
    • the loop condition is absent, and
    • the “for” statement does not use a range clause.

Put another way, a for statement is terminating if it either never ends (an infinite loop), or it unconditionally terminates.

This one “bit” me the other day, as I was refactoring code for a client. (Speaking of clients—I have some availability starting in May for a new client. Interested in having me work with you?)

The code I came across looked something like this:

for {
	select {
	case x := <-someChannel:
		/* do something interesting */
	}
}

And my linter told me I could simplify this code to:

for x := range someChannel {
	/* do something interesting */
}

Looks good, right? Simpler code FTW!

The only problem?

By making that change, the for loop was no longer a terminating statement, because it now had a range clause—it was no longer an infinite loop. As a result, the code stopped compiling, because there was no return statement after the for loop in the function. Ooops!

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