Композиция вместо наследования

В Go нет классового наследования. Вместо него — встраивание (embedding) и интерфейсы.

Встраивание структуры «поднимает» её поля и методы:

type Logger struct{}
func (l Logger) Log(msg string) { fmt.Println("[log]", msg) }

type Service struct {
    Logger           // встраивание
    Name string
}

s := Service{Name: "auth"}
s.Log("started")    // вызывает Logger.Log

Это не наследование: Service не является Logger. Но пользоваться его методами удобно.

type ReadWriter interface {
    Read() string
    Write(s string)
}

type Buffer struct {
    data string
}
func (b *Buffer) Read() string    { return b.data }
func (b *Buffer) Write(s string)  { b.data = s }

type LoggedBuffer struct {
    *Buffer            // встраивание по указателю
    Logger
}

// LoggedBuffer реализует ReadWriter через Buffer

Встроенный метод можно переопределить:

func (lb LoggedBuffer) Write(s string) {
    lb.Log("write: " + s)
    lb.Buffer.Write(s)   // явный вызов встроенного метода
}

ЗаданиеСложность
1Упражнение 1medium
2Упражнение 2medium