Адрес получателя функции варьируется между методами - PullRequest
0 голосов
/ 16 мая 2019

У меня есть следующий код.https://play.golang.org/p/YAa6cgtA3Vo

Адрес указателя получателя зависит от вызова метода.Это сбивает с толку.Кто-нибудь может объяснить, почему это так?Нужно ли передавать указатель на получателя в качестве аргумента, чтобы поддерживать тот же адрес?

type myStruct struct {
    //struct content is irrelevant
}

func (ptrToStruct *myStruct) returnAddress() **myStruct {
    return &ptrToStruct
}

func (ptrToStruct *myStruct) method1() {
    addressOfPtr := ptrToStruct.returnAddress()
    fmt.Println(&ptrToStruct)
    fmt.Println(addressOfPtr)
    if &ptrToStruct != addressOfPtr {
        fmt.Println("Different addresses!")
    }
}

РЕДАКТИРОВАТЬ:

Мне нужен адрес ptrToStruct, а не его значение,Я знаю, что я мог бы просто получить его в method1(), набрав addressOfPtr = &ptrToStruct, но в моем случае использования у меня есть некоторая логика, происходящая в методе returnAddress(), и мне нужно, чтобы он пришел оттуда.

1 Ответ

2 голосов
/ 16 мая 2019

Это просто: когда у вас есть var ms myStruct где-то, вызов ms.returnAddress() передал бы адрес переменной ms в returnAddress, и этот адрес всегда был бы одинаковым (это легко проверить - попробуйте сами).

Теперь рассмотрим, что ptrToStruct в определении returnAddress - это просто особый аргумент, передаваемый этому методу, и он имеет конкретный тип - *myStruct.

Внутренне этот тип является целым числом - достаточно большим, чтобы хранить адрес любой ячейки памяти в комбинации вашей платформы / ОС.

Теперь рассмотрим, что при выполнении вызова ms.returnAddress() адрес переменной ms берется и записывается в аргумент ptrToStruct, передаваемый returnAddress. И этот аргумент также является переменной - с временем жизни, равным продолжительности вызова функции, и видимым только в теле этой функции.

Эта переменная автоматически создается в стеке вызовов кодом, который готовит вызов функции. (И то же самое происходит со всеми остальными аргументами метода.)

Итак, когда вы берете адрес ptrToStuct, вы берете адрес переменной, появившейся в каком-то месте в стеке вызовов, который исчезнет после возврата метода.

Теперь рассмотрим, что:

  • стеки горутинов в Go могут расти (и, следовательно, могут перемещаться в памяти при выращивании);
  • метод может быть вызван из разных программ (у каждого свой стек);
  • , даже если метод вызывается из одной и той же группы несколько раз, он может вызываться из разных мест в пути кода, выполняемого этой программой.

Все вышеперечисленное может привести к тому, что адрес переменной ptrToStruct будет практически случайным от вызова к вызову.

То, что вы (вероятно) действительно хотите, это просто вернуть значение ptrToStruct как есть, а не его адрес.

Если вы чувствуете, что на самом деле не понимаете, как ptrToStruct возникает и исчезает, подумайте о том, чтобы начать с this .

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