Поведение рядом с типом
Обычная функция отдельно принимает значение: move(point, dx). Метод привязывает функцию к именованному типу, и его вызывают через точку: point.move(dx). Тип перед точкой в объявлении называется получателем метода.
Получатель-значение, например (p point), получает копию структуры. Он подходит для вычислений и чтения, но изменение p не меняет исходную переменную. Получатель-указатель, например (p *point), работает с исходным объектом и позволяет менять его поля. Для адресуемой переменной Go автоматически подставляет адрес при вызове метода с указательным получателем.
Пример
package main
import "fmt"
type point struct {
x int
y int
}
func (p *point) move(dx, dy int) {
p.x += dx
p.y += dy
}
func (p point) manhattanDistance() int {
return abs(p.x) + abs(p.y)
}
func abs(value int) int {
if value < 0 {
return -value
}
return value
}
func main() {
point := point{x: 2, y: -3}
point.move(4, 1)
fmt.Printf("точка: (%d, %d), расстояние: %d\n", point.x, point.y, point.manhattanDistance())
}
После перемещения точка равна (6, -2), расстояние до начала координат по сумме модулей равно 8. Метод чтения получает копию, что безопасно, потому что он ничего не меняет.
Выбирай указательный получатель, когда методу нужно менять состояние или структура велика и копировать её нежелательно. Для одного типа обычно придерживаются одного стиля получателей, чтобы поведение было предсказуемым. Указательный получатель нельзя вызвать на значении, которое не имеет адреса, например на временном результате функции.