Вложение в Go с указателем или значением
Я могу вставлять в golang с указателем и значением.
По указателю
type Bitmap struct{
data [4][4]bool
}
type Renderer struct{
*Bitmap
on uint8
off uint8
}
По значению
type Bitmap struct{
data [4][4]bool
}
type Renderer struct{
Bitmap
on uint8
off uint8
}
Что больше предпочитает указатель или значение?
Ответы
Ответ 1
Это зависит. Здесь есть несколько возможностей.
- Если Renderer передается по значению и методы, которые вам нужны в Bitmap, определяются на * Bitmap, тогда вам нужно встроить * Bitmap.
- Если Renderer передается как указатель, вы можете вставлять Bitmap в качестве значения без каких-либо проблем (в этом случае методы указателей будут доступны).
- Если Bitmap имеет функцию-конструктор, которая возвращает указатель, а нулевое значение Bitmap не используется, вы захотите вставить * Bitmap, так как вы не хотите поощрять копирование значения Bitmap по стоимости.
- Если все методы Bitmap являются методами значений, то вы определенно хотите вставлять по значению.
В конкретном случае, который у вас есть, я бы, вероятно, вложил по значению, поскольку тип мал - он дает вам локальность доступа и меньше распределений памяти.
Ответ 2
Встраивая тип, который вы обычно хотите использовать для переадресации вызовов. *Bitmap
- это супер-набор Bitmap
метод set. Поэтому в большинстве случаев вы захотите вставить *Bitmap
, если все его методы не имеют приемника типа Bitmap
или метод его пустым, в каких случаях вы можете избежать косвенности.
Ответ 3
Похоже, что возникает недоразумение приемников, как это выражается в ответном ответе. Методы (приемники) не определяются "указателем" или "типом", те же методы могут вызываться на значении типа в качестве указателя, сигнатура приемника определяет только, получает ли он значение типа или указатель на стоимость из-типа. То есть func(t *YourType)
можно вызвать на YourType
или &YourType
и наоборот с приемником значений. Я думаю, это должно уточнить: https://play.golang.org/p/AT1J2oGkum
Что касается вопроса о том, следует ли вставлять значение или указатель... референция действительно определяется тем, как вы имеете дело с внешним объектом, если вы передаете указатель на внешнюю структуру, у вас будет доступ к той же встроенной структуре value, если вы передаете значение внешней структуры, вы хотите, чтобы она указывала на "исходное" базовое значение встроенной структуры или копии? Я думаю, что в большинстве случаев вы либо захотите вставить указатель и указатели прохода в свою внешнюю структуру, либо вставьте значение и передайте значение своей внешней структуры.
Ответ 4
Я также счел это полезным, когда у вас есть несколько структур с одним и тем же встроенным базовым типом, и вы хотите использовать вспомогательную функцию, которая изменяет значения базовой структуры. Например, учитывая следующие структуры:
type Base struct {
F1 int
}
type A struct {
*Base
Fa int
}
type B struct {
*Base
Fb int
}
и следующую вспомогательную функцию:
func modstruct(base *Base) {
base.F1 = 2
}
все следующие вызовы функций будут компилироваться и изменять значения struct:
base := &Base{}
a := &A{Base: &Base{}}
b := &B{Base: &Base{}}
modstruct(base)
modstruct(a.Base)
modstruct(b.Base)