Перейти к разделу часто задаваемых вопросов (FAQ)
Когда параметры функции передаются по значению?
Как и во всех языках семейства C, в Go все передается по значению. То есть функция всегда получает копию передаваемой вещи, как если бы существовал оператор присваивания, присваивающий значение параметру. Например, передача значения int в функцию создает копию int, а передача значения указателя создает копию указателя, но не данных, на которые он указывает.
Должен ли я определять методы для значений или указателей?
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
Программистов, не привыкших к указателям, различие между этими двумя примерами может сбить с толку, но на самом деле ситуация очень проста. При определении метода для типа получатель (s в приведенных выше примерах) ведет себя точно так же, как если бы он был аргументом метода. Определять ли получателя как значение или как указатель — это тот же вопрос, что и должен ли аргумент функции быть значением или указателем. Есть несколько соображений.
Во-первых, и это самое главное, нужно ли модифицировать получатель в методе? Если это так, получатель должен быть указателем. (Срезы и карты действуют как ссылки, поэтому их история немного более тонкая, но, например, для изменения длины среза в методе получатель все равно должен быть указателем.) В приведенных выше примерах, если pointerMethod изменяет поля s, вызывающая сторона увидит эти изменения, но метод valueMethod вызывается с копией аргумента вызывающей стороны (это определение передачи значения), поэтому вносимые им изменения будут невидимы для вызывающей стороны.
Кстати, получатели указателей идентичны ситуации в Java, хотя в Java указатели скрыты под обложками; это приемники значения Go, которые необычны.
Во-вторых, рассмотрение эффективности. Если приемник большой, например, большая структура, будет намного дешевле использовать приемник-указатель.
Далее последовательность. Если некоторые методы этого типа должны иметь приемники указателей, остальные тоже должны иметь, чтобы набор методов был непротиворечивым независимо от того, как используется тип. Подробнее см. в разделе о наборах методов.
Для таких типов, как базовые типы, срезы и небольшие структуры, приемник значений очень дешев, поэтому, если семантика метода не требует указателя, приемник значений эффективен и понятен.