Why isn't the slice being modified in the following code:
package pointers
import "fmt"
func modifyObject(v *Vertex) {
v.x = v.x * v.x
v.y = v.y * v.y
}
func modifyArray(vertices *[]Vertex) {
for _, v := range *vertices {
v.x = v.x * v.x
v.y = v.y * v.y
}
}
func DemoPointersArray() {
v := Vertex{2, 3}
modifyObject(&v)
fmt.Println("Vertex modified successfully:", v)
v1 := Vertex{2, 3}
v2 := Vertex{20, 30}
vertices := []Vertex{v1, v2}
modifyArray(&vertices)
fmt.Println("Vertices are NOT modified:", vertices)
}
Output:
Vertex modified successfully: {4 9}
Vertices are NOT modified: [{2 3} {20 30}]
How to modify them?
The function modifyArray
modifies the local variable v
, not the slice element. Assign to the slice element using an index expression:
func modifyArray(vertices *[]Vertex) {
for i, v := range *vertices {
(*vertices)[i].x = v.x * v.x
(*vertices)[i].y = v.y * v.y
}
}
Because the slice contains a pointer to the backing array, there's no need to pass a pointer to the slice:
func modifyArray(vertices []Vertex) {
for i, v := range vertices {
vertices[i].x = v.x * v.x
vertices[i].y = v.y * v.y
}
}
Call it like this:
modifyArray(vertices) // do not take address of vertices
You can use modifyObject
by taking the address of the slice element:
func modifyArray(vertices []Vertex) {
for i := range vertices {
modifyObject(&vertices[i])
}
}
Unlike other answers, this answer retains the memory layout in the question.
In your second example you are passing a pointer to a slice. There is almost never a reason to do that as the slice is already a pointer to an array (along with a length and capacity).
Your pointer to a slice contains instances of Vertex, not *Vertex, so modifying them does not have any affect. If you instead changed your method signature to
func modifyArray(vertices []*Vertex)
and passed a slice of pointers, then you could modify them like you expect.
Here is a playground showing you by example. The corresponding code is below
package main
import "fmt"
type Vertex struct {
x int
y int
}
func modifyObject(v *Vertex) {
v.x = v.x * v.x
v.y = v.y * v.y
}
func modifyArray(vertices []*Vertex) {
for _, v := range vertices {
v.x = v.x * v.x
v.y = v.y * v.y
}
}
func main() {
v := Vertex{2, 3}
modifyObject(&v)
fmt.Println("Vertex modified successfully:", v)
v1 := Vertex{2, 3}
v2 := Vertex{20, 30}
vertices := []*Vertex{&v1, &v2}
modifyArray(vertices)
fmt.Printf("Vertices are modified: %v %v", vertices[0], vertices[1])
}