Go

What does this print? (range over an array vs a slice)

Question 48HardGo 1.22 to 1.25
arr := [3]int{1, 2, 3}
for i, v := range arr {
	arr[2] = 100
	if i == 2 {
		fmt.Println("array:", v)
	}
}

sl := []int{1, 2, 3}
for i, v := range sl {
	sl[2] = 100
	if i == 2 {
		fmt.Println("slice:", v)
	}
}

nums := []int{1, 2, 3}
for _, v := range nums {
	nums = append(nums, v)
}
fmt.Println(len(nums))

Output: array: 3, slice: 100, 6.

The range expression is evaluated once, before the loop starts. For an array, that makes a copy of the whole array (when the value variable is used), so writes to arr during the loop don't reach v. For a slice, only the header is copied. The backing array is shared, so the write is visible. Ranging over &arr or arr[:] would print 100.

The loop length is also fixed at the start. Appending during the loop does not make it longer, so there is no infinite loop and it runs exactly 3 times.

Also, v is a copy of each element, so v.Field = x on a slice of structs changes nothing. Use s[i].Field = x. Since Go 1.22 each iteration gets a fresh v, so taking &v in closures or goroutines is safe. It still does not point into the slice.

More on Arrays, Slices, Maps & Strings

All 37 Arrays, Slices, Maps & Strings questions