ТС, на твой вопрос ответа нет, потому что best practices в go завозят в малом объеме. Если тебе надо сокрыть кишочки твоей структуры, надо использовать встраивание, если тебе надо расширить структуру - используй композицию. Если тебе все равно - выбери по вкусу.
Это я понял. Я так понял, что «Embedding» это такой сахарок, что бы не копировать лишнее руками. Пока не до конца понимаю когда его лучше использовать, когде не стоит.
З.Ы.
Я имел ввиду названия точно наоборот.
Встраивание (вкладывание) - то что Embedding, когда «наследуются» поля, методы
Композиция (агрегирование) - создание ссылки внутри структуры
Если тебе надо сокрыть кишочки твоей структуры, надо использовать встраивание, если тебе надо расширить структуру - используй композицию.
Как бы дело не только в кишочках и вкусе, ты упустил, что в случае наследования - всегда будет создаваться новый экземпляр обоих структур. В твоем примере при инициализации «B» всегда будет инициализироваться «А». А в случае «расширения» можно будет один раз инициализировать «А» и использовать ссылку на нее в разных экземплярах структур «B»
Вносит путаницу в массы: полиморфного поведения то не получится, принцип Лисков не выполняется:
package main
import (
"fmt"
)
type A struct {
s string
}
type B struct {
s string
A
}
func (a A) foo() {
fmt.Println(a.s)
}
func bar(a A) {
fmt.Println("foo!")
}
func main() {
a := A{"A"}
b := B{"B", a}
//Не полиморфное поведение:
a.foo() //выведет A
b.foo() //выведет А
//Лисков не Лисков:
//foo(b) - вообще не скомпилируется
}
Без дополнительного введения интерфейсов - привычного поведения для людей, которые пользуются термином «наследование» не получишь
А в случае «расширения» можно будет один раз инициализировать «А» и использовать ссылку на нее в разных экземплярах структур «B»
слушай,я никогда так не делал конечно, но никто не запрещает делать так:
package main
import "fmt"
type A struct {
s string
}
type B struct {
*A
}
func (a A)foo(){
fmt.Println(a.s)
}
func main() {
a := A{"Same A"}
b1 := B{&a}
b2 := B{&a}
b1.foo()
b2.foo()
}