Go

Why doesn't this loop update the users?

Question 487MediumGo 1.22 to 1.25
type User struct {
    Name string
    Age  int
}

users := []User{{"ann", 30}, {"bob", 40}}
for _, u := range users {
    u.Age++
}
fmt.Println(users) // [{ann 30} {bob 40}]

u is a copy of each element. Incrementing it changes the copy, which is thrown away at the end of the iteration. Go 1.22's per-iteration variables do not change this. Each iteration just gets its own copy.

Fixes:

for i := range users {
    users[i].Age++          // index into the slice
}

for i := range users {
    u := &users[i]          // pointer to the element
    u.Age++
}

A slice of pointers ([]*User) also works, because the copied value is then a pointer. Code-review angle: with large structs, for _, u := range also copies every element on every iteration, which costs CPU. Linters such as gocritic rangeValCopy flag it. Maps have the same issue, and the fix is worse: you cannot take the address of a map element (&m[k] does not compile), so you must read, modify, and write back with m[k] = u.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions