如何使用指针修改切片

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

playground example

You can use modifyObject by taking the address of the slice element:

 func modifyArray(vertices []Vertex) {
    for i := range vertices {
        modifyObject(&vertices[i])
    }
}

playground example

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).

enter image description hereenter image description here

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])
}