Вложение в 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)