Как изменить ломтики с помощью указателей - PullRequest
0 голосов
/ 28 апреля 2018

Почему срез не изменяется в следующем коде:

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

Выход:
Вершина изменена успешно: {4 9}
Вершины НЕ изменены: [{2 3} {20 30}]

Как их изменить?

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Функция modifyArray изменяет локальную переменную v, а не элемент слайса. Присвойте элементу фрагмента, используя индексное выражение:

func modifyArray(vertices *[]Vertex) {
    for i, v := range *vertices {
        (*vertices)[i].x = v.x * v.x
        (*vertices)[i].y = v.y * v.y
    }
}

Поскольку срез содержит указатель на резервный массив, нет необходимости передавать указатель на срез:

func modifyArray(vertices []Vertex) {
    for i, v := range vertices {
        vertices[i].x = v.x * v.x
        vertices[i].y = v.y * v.y
    }
}

Назовите это так:

modifyArray(vertices)  // do not take address of vertices

пример детской площадки

Вы можете использовать modifyObject, взяв адрес элемента slice:

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

пример детской площадки

В отличие от других ответов, этот ответ сохраняет структуру памяти в вопросе.

0 голосов
/ 28 апреля 2018

Во втором примере вы передаете указатель на срез. Почти никогда нет причин делать это, так как срез уже является указателем на массив (вместе с длиной и емкостью).

enter image description here enter image description here

Ваш указатель на срез содержит экземпляры Vertex, а не * Vertex, поэтому их изменение не оказывает никакого влияния. Если вы вместо этого изменили подпись вашего метода на

func modifyArray(vertices []*Vertex) 

и передал часть указателей, тогда вы можете изменить их, как вы ожидаете.

Вот игровая площадка , показывающая вам пример. Соответствующий код ниже

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])
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...