Что там - различие, когда Вы получаете доступ к другой структуре значением или указателем?
Когда должен использоваться каждый из них?
type foo_ struct {
st uint8
nd uint8
}
type bar struct {
rd uint8
foo foo_
}
type barP struct {
rd uint8
foo *foo_
}
Если вы объявляете или выделяете переменную типа 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
}
Ответ в значительной степени не зависит от языка - эквивалент в C имеет те же проблемы.
Когда у вас есть встроенное значение (как в bar
), ваша структура достаточно велика, чтобы вместить всю подструктуру и другую часть.
Если у вас есть указатель на значение (как в barP
), тогда несколько структур типа barP
могут совместно использовать один и тот же foo
. Когда любая из barP
изменяет часть foo
, на которую указывает, это влияет на все остальные структуры barP
, которые указывают на то же место. Кроме того, как следует из комментария, вы должны управлять двумя отдельными объектами - barP
и foo
, а не одним с обычным типом bar
.
В некоторых языках вам придется беспокоиться о висячих указателях, неинициализированных значениях и т. Д .; Go собирает мусор и, как правило, более безопасен по сравнению с другими языками.
Итак, используйте указатель, если вы хотите, чтобы несколько объектов barP
совместно использовали один и тот же объект foo
; в противном случае используйте явный объект-член, а не указатель на объект.