Коротко: в Go нет классов и наследования: данные — структуры, поведение — методы, контракты — интерфейсы (реализуются неявно); композиция вместо иерархий.
Коротко: в Go нет классов и наследования. Данные описываются структурами, поведение — методами, а контракты — интерфейсами, причём интерфейсы реализуются неявно. Для PHP-разработчика это смена парадигмы: вместо иерархий наследования — композиция и маленькие интерфейсы. Разберём на параллелях с PHP.
Структура вместо класса-данных
Там, где в PHP вы бы завели класс со свойствами, в Go используется структура:
type User struct {
Name string
Email string
Age int
}
u := User{Name: "Лео", Email: "leo@example.com", Age: 36}
Это чистый контейнер данных. Никакого private/public на уровне ключевых слов — видимость определяется регистром первой буквы: Name (с большой) экспортируется из пакета, name (с маленькой) — приватно для пакета.
Методы вместо методов класса
Метод в Go — это функция с «получателем» (receiver). Он привязывается к типу, но объявляется отдельно от структуры:
func (u User) FullInfo() string {
return u.Name + " <" + u.Email + ">"
}
// указательный получатель — если нужно менять состояние
func (u *User) Birthday() {
u.Age++
}
Различие (u User) и (u *User) важно: первый работает с копией, второй — с указателем и может менять оригинал. В PHP объекты всегда передаются по ссылке-хэндлу, в Go вы выбираете явно.
Интерфейсы — и тут главное отличие
Интерфейс в Go описывает набор методов. Но реализуется он неявно: типу не нужно писать implements — достаточно иметь нужные методы:
type Greeter interface {
Greeting() string
}
type User struct{ Name string }
func (u User) Greeting() string { return "Привет, " + u.Name }
// User автоматически удовлетворяет Greeter — никаких implements
var g Greeter = User{Name: "Лео"}
Сравните с PHP, где нужно явно class User implements Greeter. В Go связь «утиная»: «если крякает как утка — значит утка». Это развязывает код: интерфейс можно объявить там, где он используется, не трогая тип, который его реализует.
Маленькие интерфейсы вместо больших
Идиома Go — интерфейсы из одного-двух методов. Классика — io.Writer:
type Writer interface {
Write(p []byte) (n int, err error)
}
Функции принимают узкий интерфейс, а не конкретный тип, — и работают с чем угодно, что его реализует (файл, сеть, буфер). В PHP к этому приходят через интерфейс-сегрегацию (буква I в SOLID); в Go это встроенная культура.
Композиция вместо наследования
Наследования классов в Go нет. Переиспользование — через встраивание (embedding) структур и интерфейсов:
type Timestamps struct {
CreatedAt time.Time
UpdatedAt time.Time
}
type Article struct {
Timestamps // встроено: поля и методы Timestamps доступны напрямую
Title string
}
a := Article{}
a.CreatedAt = time.Now() // доступ как к собственному полю
Это «has-a», а не «is-a». Никаких хрупких глубоких иерархий — то, к чему в PHP приходят осознанно («композиция вместо наследования»), в Go является способом по умолчанию.
Полиморфизм через интерфейсы
Полиморфизм в Go достигается интерфейсами + (при необходимости) type switch:
func describe(i interface{}) string {
switch v := i.(type) {
case User:
return "пользователь " + v.Name
case int:
return "число " + strconv.Itoa(v)
default:
return "что-то ещё"
}
}
Шпаргалка соответствий PHP → Go
- класс с данными →
struct; - метод класса → функция с receiver;
implements Interface→ ничего (неявная реализация);- наследование (
extends) → встраивание (embedding), композиция; abstract/контракт → интерфейс (маленький);- видимость
public/private→ регистр первой буквы имени.
Главный сдвиг мышления: в Go вы проектируете вокруг поведения (интерфейсов) и композиции, а не вокруг иерархий классов. Если переносите PHP-домен на Go и не уверены, как разложить модель на структуры и интерфейсы, — разберём на консультации.


Комментарии