Ответ
Ресивер-значение (value receiver) — это когда метод вызывается у копии объекта, а не у самого объекта. Это основной способ обеспечить неизменяемость (immutability).
Плюсы:
- Неизменяемость и безопасность: Метод получает копию данных. Любые изменения внутри метода не затрагивают оригинальный объект, что защищает от непреднамеренных побочных эффектов.
- Потокобезопасность: Так как оригинальные данные не изменяются, вызовы таких методов для одного и того же значения из разных горутин безопасны и не вызывают гонок данных.
- Простота: Не нужно беспокоиться о
nil
-указателях, так как вы всегда работаете с конкретным значением.
Минусы:
- Накладные расходы на производительность: При каждом вызове метода создается копия структуры. Для больших структур это может быть затратно по памяти и времени.
- Невозможность изменить исходный объект: Если метод должен изменять состояние объекта (например, инкрементировать счетчик), ресивер-значение для этого не подходит.
Когда использовать: Идеально подходит для небольших структур, которые можно рассматривать как неизменяемые значения (например, time.Time
), или когда важно гарантировать, что метод не изменит состояние объекта.
Пример:
package main
import "fmt"
type Point struct {
X, Y int
}
// Метод с ресивером-значением. Работает с копией `p`.
func (p Point) Move(dx, dy int) Point {
p.X += dx // Изменяется только копия
p.Y += dy
return p // Возвращается измененная копия
}
func main() {
p1 := Point{1, 2}
p2 := p1.Move(10, 20) // Метод вернул новый объект
fmt.Printf("Original Point p1: %+vn", p1) // Выведет: Original Point p1: {X:1 Y:2}
fmt.Printf("New Point p2: %+vn", p2) // Выведет: New Point p2: {X:11 Y:22}
}