Почему значение меняется после выполнения функции? - PullRequest
0 голосов
/ 14 октября 2018

Я сейчас учу себя Го, и у меня возникают проблемы с пониманием определенного поведения:

package main

import (
    "fmt"
)

type List struct {
    n int
}

func (l List) Increment() {
    l.n += 1
    l.LogState() // size: 1
}

func (l List) LogState() {
    fmt.Printf("size: %v\n", l.n)
}

func main() {
    list := List{}
    list.Increment()

    fmt.Println("----")
    list.LogState() // size: 0
}

https://play.golang.org/p/-O24DiNPkxx

LogState выполняется дважды.В начальный момент времени при вызове Increment он печатает size: 1, но после возврата Increment печатает size: 0.Почему эти значения разные?

Ответы [ 2 ]

0 голосов
/ 14 октября 2018

Причина, по которой ваши узлы не добавляются в исходный связанный список ссылок, потому что вы не используете указатель на структуру.Так что даже если функция Increment в вашем примере кода изменяет значение.Копия структуры изменена, а не фактическая структура.

Вы можете объявить методы с указателями получателей.Это означает, что тип получателя имеет буквальный синтаксис * T для некоторого типа T. (Кроме того, T сам по себе не может быть указателем, например * int.)

Если вы хотите изменить структурный счетчик connectedlistNode напокажите узлы, добавленные в список, вы должны использовать приемник с типом указателя в обоих методах, работающих для изменения связанного списка, следующим образом:

func (l *LinkedList) AddInitialValue(v interface{})
func (l *LinkedList) LogState()

И внутри главной передачи передать адрес связанный список, чтобы использовать этот тип указателяприемники как:

func main() {
    list :=  &LinkedList{}
    list.AddInitialValue(9)

    fmt.Println("----")
    list.LogState() // size: 0
}

Рабочий код Игровая площадка

Примечание: -

Существует две причины для использованияприемник указателя.

  • Для изменения значения, на которое указывает его приемник.
  • Чтобы избежать копирования значения при каждом вызове метода.Это может быть более эффективным, если получатель имеет большую структуру

Для получения дополнительной информации просмотрите Наборы методов

0 голосов
/ 14 октября 2018

Когда Increment и LogState определены так, как вы их определили, вы работаете только с копией со значением List.Это означает, что если вы сделаете некоторые изменения внутри функции Increment, они будут видны только внутри области действия Increment и только до конца существования этой конкретной области.Чтобы подтвердить, что вы всегда работаете с копией исходного значения List, вы можете войти &list перед выполнением функции Increment и &l внутри одной и той же функции.

Если вы хотите сделатьИзменения постоянные, вы должны работать с указателем на адрес памяти.Это означает, что ваша ваша функция должна быть определена следующим образом:

func (l *List) Increment()

func (l *List) LogState()

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

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