函数返回的结构在其所属的数组中未更改

I am writing a small GUI-application in Gotk3, this is my basic setup in pseudo-code:

type Point struct {
    X float64
    Y float64
    IsSelected bool
}

func getClosestElement(pT []Point, p Point, maxDist float64) Point {
    /* returns the point from pT with the minimum distance to p */
}

func main() {
    // GTK init ..
    selectedPoints := make([]Point, 0)

    /* GTK-Event onMouseClick */
    {
        /* if left mouse click */
        selectedPoints = append(selectedPoints, Point{X: event.x, Y: event.y})
        /* if right mouse click */
        closestPoint = getClosestElement(selectedPoints, Point{X: event.x, Y: event.y}, 15.0)
        closestPoint.IsSelected = true
    }

    /* GTK-Event Draw */
    {
        /* Loop over all selectedPoints */
        if selectedPoint.IsSelected
        /* Draw point in blue and also print to console, if a selected point was detected */
        else
        /* Draw point in black */
    }
}

But somehow, even though getting the closest Point from selectedPoints works fine, I never get the console output for looping over a point which IsSelectedproperty is true nor do I get a blue drawn point (which would indicate that this point is selected).

This leaves me with the question if a returned struct, which was part of a slice which was initialy given to the function, is actually returned by value instead of by reference. So a change to this returned point doesn't change the point in the array it former belonged to?

If you push a non pointer value in a slice, and then a function returns a value from that slice, it will be a copy of that value. Therefore if you change a property of that value, it won't affect the value in the slice.

You can either:

  • Make your Point pointer values, eg *Point
  • Have a function called selectClosestElement which sets the IsSelected to true and replaces the value in the slice.

Example:

// With pointers
// GTK init ..
    selectedPoints := make([]*Point, 0)

    /* GTK-Event onMouseClick */
    {
        /* if left mouse click */
        selectedPoints = append(selectedPoints, &Point{X: event.x, Y: event.y})
        /* if right mouse click */
        closestPoint = getClosestElement(selectedPoints, &Point{X: event.x, Y: event.y}, 15.0)
        closestPoint.IsSelected = true
    }
// With a selectClosestPoint function replacing the value in the slice
// GTK init ..
    selectedPoints := make([]Point, 0)
    /* GTK-Event onMouseClick */
    {
        /* if left mouse click */
        selectedPoints = append(selectedPoints, Point{X: event.x, Y: event.y})
        /* if right mouse click */
        selectClosestPoint(selectedPoints, Point{X: event.x, Y: event.y}, 15.0)
    }
...

func selectClosestPoint(selectedPoints []Point, point Point, maxDist float64) {
    for i, sPoint := range selectedPoints {
        // ...
        // this is the correct point
        sPoint.IsSelected = true
        // Replace it in the slice
        selectedPoints[i] = sPoint
    }
}