-2

I am defining struct of Ball and declare moveBall function with pointer receiver to change its position. My initial code was this, using for-range loop.

package main

import (
    "fmt"
)

type Ball struct {
    X float32
    Y float32
}

func main() {
    ballSlice := []Ball{Ball{X: 1, Y: 2}, Ball{X: 3, Y: 4}}

    fmt.Println("Before update")
    fmt.Printf("Ball 1: %v", ballSlice[0])

    for _, elem := range ballSlice {
        elem.moveBall()
    }
    fmt.Println("\n\nAfter update")
    fmt.Printf("Ball 1: %v", ballSlice[0])
}

func (ball *Ball) moveBall() {
    ball.X += 20
    ball.Y += 20
}

Output

Before update
Ball 1: {1 2}

After update
Ball 1: {1 2}

The output shows that the X and Y value does not change.

However, when I am using the index, the value changed

...
    for idx := range ballSlice {
        ballSlice[idx].moveBall()
    }
...

Output

Before update
Ball 1: {1 2}

After update
Ball 1: {21 22}

Is this the intended behavior in Golang or there is something wrong with my code?

Akhmad Zaki
  • 419
  • 7
  • 23
  • There is only a single, loop variable, `elem` in your case. The `for range` will copy each element to this loop variable, and so any modifications made on it will be overwritten in the next iteration. One solution is to index the slice like `ballSlice[idx].moveBall()`, another is to store pointers in the slice, so use `[]*Ball`. You should do this anyway since you have methods with pointer receivers, so you avoid surprises like this. – icza Aug 27 '23 at 06:57

0 Answers0