A Go output-prediction question about a for loop that appends the address of its loop variable on every iteration and prints the stored values afterwards. It tests loop-variable semantics across Go language versions, escape analysis, and whether such pointers are safe to dereference.
Predict the Output of Go Code Storing Pointers to a for-Loop Variable
Company: Zoox
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
Without running it, predict what this Go program prints, and explain why.
```go
package main
import "fmt"
func main() {
var a []*int
for i := 0; i < 3; i++ {
a = append(a, &i)
}
for _, b := range a {
fmt.Println(*b)
}
}
```
This was an output-prediction exercise: the code alone, with a request for its output.
```hint Count the variables
Work out how many distinct variables the three `&i` expressions can point to, and what each one holds when the second loop reads it.
```
```hint Consider the toolchain
Ask whether your answer would be the same for every Go release, and what in a build selects the rules for a loop's variable.
```
### Clarifying Questions
- Which Go release builds the program, and which language version does its module declare in `go.mod`?
- Should the answer also cover whether the program can crash, or only what it prints?
### What a Strong Answer Covers
- The output with one variable shared by the whole loop and with a fresh variable for every iteration, tracing the value each stored pointer sees
- What decides which rule applies, and which kinds of `for` loops it covers
- What happens to the memory behind `&i` once the loop has ended, and whether dereferencing the stored pointers is safe
- A way to write the loop so that it prints the same values in every Go release
### Follow-up Questions
- A candidate argues that `i` goes out of scope when the loop ends, so dereferencing the stored pointers panics. Is that right, and what does the compiler actually do with `i`?
- Replace the loop body with `go func() { fmt.Println(i) }()` and wait for the goroutines to finish. What can it print under each rule?
- If the loop body sometimes runs `i++` itself, which value does the next iteration start from under the per-iteration rule?
- Does giving every iteration its own variable cost anything at run time, and in which cases?
Overview: A Go output-prediction question about a for loop that appends the address of its loop variable on every iteration and prints the stored values afterwards. It tests loop-variable semantics across Go language versions, escape analysis, and whether such pointers are safe to dereference.
Without running it, predict what this Go program prints, and explain why.
package main
import "fmt"
func main() {
var a []*int
for i := 0; i < 3; i++ {
a = append(a, &i)
}
for _, b := range a {
fmt.Println(*b)
}
}
This was an output-prediction exercise: the code alone, with a request for its output.
Clarifying Questions Guidance
Which Go release builds the program, and which language version does its module declare in
go.mod
?
Should the answer also cover whether the program can crash, or only what it prints?
What a Strong Answer Covers Guidance
The output with one variable shared by the whole loop and with a fresh variable for every iteration, tracing the value each stored pointer sees
What decides which rule applies, and which kinds of
for
loops it covers
What happens to the memory behind
&i
once the loop has ended, and whether dereferencing the stored pointers is safe
A way to write the loop so that it prints the same values in every Go release
Follow-up Questions Guidance
A candidate argues that
i
goes out of scope when the loop ends, so dereferencing the stored pointers panics. Is that right, and what does the compiler actually do with
i
?
Replace the loop body with
go func() { fmt.Println(i) }()
and wait for the goroutines to finish. What can it print under each rule?
If the loop body sometimes runs
i++
itself, which value does the next iteration start from under the per-iteration rule?
Does giving every iteration its own variable cost anything at run time, and in which cases?