Feature Image 1

# Golang Range Loop Reference - Why Your Loop Keeps Giving You the Same Pointer (and How to Fix It)

Table of Contents

When I first started learning Go, I thought I was doing everything right—until I ran into a weird bug about golang range loop reference. I was iterating over a list of Book structs (of course, I can’t share the real structs and code used here… all here are for turorial purpose), taking the pointer of each one, and storing them into a slice. But at the end of the loop, all the pointers pointed to… the same book?! 🤯

Let’s walk through this classic Go beginner mistake together — and fix it the right way.

📚 The Use Case: A Slice of Books in a Library

Suppose we have a list of books, and we want to collect pointers to each one so we can modify them later.

Here’s the code I thought would work:

for _, book := range books {
bookPointers = append(bookPointers, &book) // Oops...
}

But when I printed out the pointers, they all pointed to the last book in the list. This bug stumped me for a while until I understood one critical Go behavior.

The File Structure To Run The Code

learning-golang/
├── 01-loop-reference-pitfall/
│ ├── main.go
│ └── README.md
├── Makefile
├── bin/
└── go.mod

This is the complete buggy code:

package main
import (
"fmt"
)
type Book struct {
Title string
Author string
}
func main() {
originalBooks := []Book{
{"Go in Action", "William Kennedy"},
{"The Go Programming Language", "Alan Donovan"},
{"Introducing Go", "Caleb Doxsey"},
}
fmt.Println("❌ Buggy Version:")
var buggyPointers []*Book
for _, book := range originalBooks {
buggyPointers = append(buggyPointers, &book)
}
for _, bp := range buggyPointers {
fmt.Printf("Title: %-30s | Address: %p\n", bp.Title, bp)
}
}

The Makefile:

# Usage:
# make run DIR=01-loop-reference-pitfall
# make build DIR=01-loop-reference-pitfall
# make clean
GO=go
run:
@echo "👉 Running $(DIR)/main.go..."
cd $(DIR) && $(GO) run main.go
build:
@echo "🔧 Building binary from $(DIR)/main.go..."
cd $(DIR) && $(GO) build -o ../bin/$(notdir $(DIR))
clean:
@echo "🧹 Cleaning up built binaries..."
rm -rf bin/

Build and Run The Code

❯ go mod init github.com/geekcoding101/learning-golang
❯ make run DIR=01-loop-reference-pitfall

Golang Range Loop Reference - First time build and run code
Golang Range Loop Reference - First time build and run code

As you see, the Address didn’t change at all!


🐛 The Problem: Reuses the Loop Variable in Golang Range Loop Reference

In Go, when you do:

for _, book := range books

The book variable is reused in every iteration. It’s not a new instance each time. So taking &book actually gives you the same memory address over and over.

This means every pointer in the slice is just pointing to the same memory location, which at the end holds the value of the last book.


The Fix: Indexing Directly

The correct way is to use an index:

fmt.Println("\n✅ Fixed Version:")
var fixedPointers []*Book
for i := range originalBooks {
fixedPointers = append(fixedPointers, &originalBooks[i])
}
for _, bp := range fixedPointers {
fmt.Printf("Title: %-30s | Address: %p\n", bp.Title, bp)
}

Now, each pointer actually refers to the corresponding element in the original slice. Problem solved!

second time with fix build and run
second time with fix build and run


💻 Real Code Example on GitHub

I’ve documented this bug and fix in my GitHub repository:

👉 github.com/geekcoding101/learning-golang

Here’s what you’ll find:

  • The buggy version (with all pointers pointing to the same book)

  • The fixed version (each pointer is correct)

  • A Makefile to help you run and build each learning topic


✍️ Follow My Golang Tutorials

I’ll continue sharing these hands-on lessons as I deepen my understanding of Go.

Check out my blog 👉 www.geekcoding101.com — where I share practical posts, breakdowns, and real-world insights from my coding journey.


📌 Quick Hashtag

#Golang Range Loop Reference, #for loop golang range, #for loop range golang, #golang for range loop, #for loop in golang with range, #go slice reference, #go for loop pointer trap, #why does my go loop store the same pointer, #golang how to correctly get pointer from loop, #go for loop pointer always same

My avatar

Thanks for reading my blog post! Feel free to check out my other posts or contact me via the social links in the footer.


More Posts