paulgorman.org

Golang pass-by-value in “for … range” loops

Most things in Go pass by value, but this one still surprised me.

func main() {
	points := []Point{{x: 1, y: 1}}
	for _, p := range points {
		p.x += 1
	}
	fmt.Println(points[0].x) // Expected "2" but got "1". :(
}

range returns a copy of the value in each iteration of the loop. Changes to the copy don’t survive exit of the loop. If we want changes to persist, we need to modify the original:

// Demonstrate pass-by-value in "for" loops.
package main

import "fmt"

type Point struct {
	x int
	y int
}

func main() {
	points := []Point{{x: 1, y: 1}}
	for i, p := range points {
		fmt.Println(p.x) // 1
		p.x += 1
		fmt.Println(p.x)         // 2
		fmt.Println(points[i].x) // 1 not 2! "p" is only a copy of points[i].
		points[i].x += 1 // This modifies the original value, outside the loop.
	}
	fmt.Println(points[0].x) // 2
}

#golang

⬅ Older Post Newer Post ➡