// метод для указателя
func (s *MyStruct) pointerMethod() { }
// метод для значения
func (s MyStruct) valueMethod() { }
Для программистов, не привыкших к указателям, различие между этими двумя примерами может сбивать с толку, но на самом деле ситуация очень проста. При определении метода для типа получатель (s
в приведенных выше примерах) ведет себя точно так же, как если бы это был аргумент метода. Определять ли получатель как значение или как указатель - это тот же вопрос что и, должен ли аргумент функции быть значением или указателем? Есть несколько соображений по этому поводу.
Во-первых, и это наиболее важно, метод должен изменить получатель? Если это так, получатель должен быть указателем. (Срезы и карты выступают в качестве ссылок, поэтому их история немного более тонкая, но, например, для изменения длины среза в методе получатель должен быть указателем.) В приведенных выше примерах, если pointerMethod
изменяет поля s
, вызывающая сторона увидит эти изменения, но valueMethod
вызывается с копией аргумента вызывающей стороны (это определение передачи значения), поэтому изменения, которые он вносит, будут невидимы для вызывающей стороны.
Кстати, в Java приемники методов всегда указатели, хотя их указательный характер несколько замаскирован (существует предложение добавить приемники значения к языку).
Во-вторых, учет эффективности. Если приемник большой, например, большая struct
, это будет намного дешевле использовать указатель приемника.
Следующее - последовательность. Если некоторые из методов типа должны иметь приемник указателя, остальные тоже должны, поэтому набор методов соответствует независимо от того, как используется тип.
Для таких типов, как базовые типы, срезы и небольшие struct
, получатель значения очень дешев, поэтому, если семантика метода требует указателя, получатель значения эффективен и понятен.
Читайте также:
Комментариев нет:
Отправить комментарий