Go

What does this print? (range over a nil pointer to an array, and range over an int)

Question 74HardGo 1.22 to 1.25
func main() {
	var p *[3]int
	fmt.Println(len(p))

	for i := range p {
		fmt.Print(i, " ")
	}
	fmt.Println()

	for i := range 3 { // Go 1.22 range-over-int
		fmt.Print(i, " ")
	}
	fmt.Println()

	defer func() { fmt.Println("recovered:", recover()) }()
	for i, v := range p {
		fmt.Println(i, v)
	}
}

Output:

3
0 1 2
0 1 2
recovered: runtime error: invalid memory address or nil pointer dereference

For an array or a pointer to an array, len(p) is a compile-time constant (3). The pointer is never dereferenced, so it works even when p is nil. The spec says the range expression is evaluated once, with one exception: when there is at most one iteration variable and len(x) is constant, the range expression is not evaluated at all. So for i := range p just counts 0 to 2.

With two variables, the loop must read p[i], which dereferences the nil pointer and panics.

for i := range n (Go 1.22) evaluates n once and loops from 0 to n-1. If n is 0 or negative, the loop body never runs. The type of i is the type of n. With an untyped constant, i is int.

More on Arrays, Slices, Maps & Strings

All 37 Arrays, Slices, Maps & Strings questions