Перейти к основному содержимому

Ресиверы (Receivers) - Аналог this и self

В Go нет классов. Вместо этого мы объявляем обычные функции и «привязываем» их к определенному типу (обычно к структуре). Такая привязанная функция называется методом.

Синтаксис метода выглядит так:

func (d Dog) Speak() string {
return "Woof!"
}

Блок (d Dog) перед именем функции называется ресивером (получателем).

Что означает d?

  • d — это просто имя переменной, через которую ты обращаешься к конкретному экземпляру структуры внутри метода.
  • Это полный аналог ключевого слова this в Java/C++/JS или self в Python.
  • Разработчики Go специально отказались от зарезервированных слов this или self, заставив программиста явно объявлять переменную.

Конвенция именования (Best Practice)

В Go не принято называть ресивер this, self или me. Общепринятый стандарт — использовать первую букву названия типа (в нижнем регистре) или короткую аббревиатуру:

  • Для типа Dog ресивер называют d.
  • Для типа Useru.
  • Для типа HTTPClientc или client.

Как это используется?

Через переменную d мы получаем доступ к полям именно той собаки, для которой вызвали метод:

type Dog struct {
Name string
Age int
}

// Метод привязан к типу Dog
func (d Dog) Speak() string {
// Обращаемся к полю Name конкретной собаки через ресивер 'd'
return d.Name + " говорит: Woof!"
}

func main() {
myDog := Dog{Name: "Шарик"}
fmt.Println(myDog.Speak()) // Вывод: Шарик говорит: Woof!
}

Value vs Pointer Receiver

Это обязательно спросят: "В чем разница между (d Dog) и (d *Dog)?"

1. Value Receiver (Передача по значению)

func (d Dog) ChangeName() {
d.Name = "Бобик" // Изменит только КОПИЮ
}
  • Как работает: Когда ты вызываешь этот метод, Go создает полную копию всей структуры Dog и передает её в метод.
  • Следствие: Любые изменения полей внутри метода не повлияют на оригинальную структуру.
  • Когда использовать: Если структура маленькая, и метод только читает данные, но не изменяет их.

2. Pointer Receiver (Передача по указателю)

func (d *Dog) ChangeName() {
d.Name = "Бобик" // Изменит ОРИГИНАЛ
}
  • Как работает: В метод передается не копия структуры, а указатель (ссылка) на неё в памяти.
  • Следствие: Изменения полей внутри метода отразятся на оригинальной структуре.
  • Когда использовать:
    1. Если метод должен изменять состояние структуры.
    2. Если структура очень большая (много полей), чтобы не тратить память и процессорное время на её копирование при каждом вызове.

Золотое правило: Если хотя бы один метод твоей структуры требует Pointer receiver (*Dog), то конвенция диктует делать все методы этой структуры с Pointer receiver для единообразия, даже если некоторые из них структуру не меняют.