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 IsSelected
property 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:
Point
pointer values, eg *Point
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
}
}