Как в Go реализовать методы для структуры?

Ответ

В Go функциональность, привязанная к определенному типу (например, к структуре), реализуется с помощью методов. Метод — это функция со специальным аргументом, называемым получателем (receiver), который указывается перед именем функции.

Получатель связывает функцию с типом. Он может быть двух видов: по значению или по указателю.

import "fmt"

type Rectangle struct {
    Width, Height float64
}

// Метод с получателем по значению (value receiver)
// Работает с копией структуры. Не может изменять исходный объект `r`.
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Метод с получателем по указателю (pointer receiver)
// Работает с оригиналом структуры через указатель. Может изменять исходный объект `r`.
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

Когда какой получатель выбирать?

  1. *Используйте получатель-указатель (`T`), если:**

    • Метод должен изменять состояние исходного объекта.
    • Структура имеет большой размер. Передача указателя намного эффективнее, чем копирование всей структуры.
  2. Используйте получатель-значение (T), если:

    • Метод не должен изменять состояние объекта (например, методы для вычислений или форматирования).
    • Структура маленькая (например, базовые типы, time.Time) и ее копирование не несет больших накладных расходов.
    • Нужно гарантировать, что метод не изменит исходное значение (безопасность для конкурентного выполнения).

Важное замечание: Go предоставляет синтаксический сахар. Вы можете вызывать метод с указателем на переменной-значении (rect.Scale(2)) и наоборот. Компилятор автоматически преобразует rect в &rect (и наоборот), если это необходимо.