Доступ к другой структуре значением или указателем

Что там - различие, когда Вы получаете доступ к другой структуре значением или указателем?
Когда должен использоваться каждый из них?

type foo_ struct {
    st uint8
    nd uint8
}

type bar struct {
    rd  uint8
    foo foo_
}

type barP struct {
    rd  uint8
    foo *foo_
}
6
задан Flimzy 9 July 2017 в 08:49
поделиться

2 ответа

Если вы объявляете или выделяете переменную типа bar , вы резервируете и инициализируете нулевую память для обоих rd uint8 и foo foo_ . Всегда есть одна переменная типа foo_ , встроенная в переменную типа bar .

var b bar  // declare b

Если вы объявляете или выделяете переменную типа barP , вы резервируете и инициализируете нулевую память для обоих rd uint8 и foo * foo_ . Указатель нулевого значения - это указатель nil . Переменная типа foo_ не выделяется; вы должны делать это отдельно. Имеется либо ноль ( foo == nil ), либо одна переменная типа foo_ , на которую указывает переменная типа barP . Переменная типа barP может указывать на ту же переменную типа foo_ , что и другие переменные типа barP , совместно используя одну и ту же копию переменной введите foo_ . Изменение общей копии видят все переменные, которые на нее указывают.

var bp barP         // declare bp
bp.foo = new(foo_)  // allocate bp.foo

Какой из них использовать, зависит от свойств типа bar по сравнению с типом barP . Какой тип более точно отражает проблему, которую вы пытаетесь решить?

Например, рассмотрим эту проблему со счетом. У нас всегда есть платежный адрес; мы всегда будем просить наши деньги. Однако мы часто отправляем на адрес выставления счета, но не всегда. Если адрес доставки nil , используйте адрес для выставления счетов. В противном случае используйте отдельный адрес доставки. У нас два склада, и мы всегда отправляем с одного или другого.Мы можем поделиться двумя складскими помещениями. Поскольку мы не отправляем счет-фактуру до тех пор, пока заказ не будет отправлен со склада, местоположение склада никогда не будет ноль .

type address struct {
    street string
    city   string
}

type warehouse struct {
    address string
}

type invoice struct {
    name      string
    billing   address
    shipping  *address
    warehouse *warehouse
}
5
ответ дан 10 December 2019 в 02:44
поделиться

Ответ в значительной степени не зависит от языка - эквивалент в C имеет те же проблемы.

Когда у вас есть встроенное значение (как в bar ), ваша структура достаточно велика, чтобы вместить всю подструктуру и другую часть.

Если у вас есть указатель на значение (как в barP ), тогда несколько структур типа barP могут совместно использовать один и тот же foo . Когда любая из barP изменяет часть foo , на которую указывает, это влияет на все остальные структуры barP , которые указывают на то же место. Кроме того, как следует из комментария, вы должны управлять двумя отдельными объектами - barP и foo , а не одним с обычным типом bar .

В некоторых языках вам придется беспокоиться о висячих указателях, неинициализированных значениях и т. Д .; Go собирает мусор и, как правило, более безопасен по сравнению с другими языками.

Итак, используйте указатель, если вы хотите, чтобы несколько объектов barP совместно использовали один и тот же объект foo ; в противном случае используйте явный объект-член, а не указатель на объект.

2
ответ дан 10 December 2019 в 02:44
поделиться