При передаче методного выражения в функцию-колбэк какой аргумент должен явно предоставить вызывающий код?
При вызове методного выражения получатель метода передаётся явно первым аргументом. Поэтому методное выражение имеет сигнатуру обычной функции: для метода с получателем типа T это функция, принимающая T первым параметром.
Методы в Go отделены от самих функций, но язык позволяет обращаться к методу как к значению функции. Такой подход поддерживает передачу поведения в колбэки и другие функции высшего порядка без создания отдельной обёртки.
Методное выражение сохраняет связь с выбранным методом, но не фиксирует конкретный экземпляр получателя. Это отличает его от методного значения, которое уже содержит получатель.
Если передать методное выражение в функцию-колбэк и не учесть получатель, тип функции не совпадёт с ожидаемым. Компилятор потребует явно передать значение получателя при вызове.
Неверное понимание этого механизма приводит к лишним замыканиям, ошибкам типов при передаче колбэков и путанице между T.M как методным выражением и value.M как методным значением.
Для метода со значимым получателем выражение T.M превращается в функцию, где получатель становится первым параметром. Например, Counter.Add имеет тип функции func(Counter, int) int, а не func(int) int.
Здесь Counter.Add не хранит конкретное значение Counter. При вызове f(c, 2) сначала передаётся получатель c, затем обычный аргумент метода 2.
Для метода с указательным получателем методное выражение выбирают через указательный тип. Вызов такого выражения также получает указатель первым аргументом, поэтому возможна передача nil, если это допускает тело метода; паника возникнет только при фактическом некорректном обращении внутри метода.
Главное отличие от методного значения состоит в моменте связывания получателя. Методное выражение (T.M) оставляет получатель явным, а методное значение (value.M) захватывает конкретный value при создании значения функции.
В обработчике нужно передать операцию над объектом в универсальный исполнитель. Можно создать замыкание, которое захватывает объект: это удобно, поскольку колбэк получает меньше аргументов, но появляется дополнительная обёртка и скрытая зависимость от захваченного состояния.
Второй вариант — передать методное выражение. Тогда тип колбэка явно показывает, что объект является отдельным входом операции; одно и то же значение функции можно применять к разным объектам.
Для универсального исполнителя выбран второй вариант: он уменьшает число замыканий и делает контракт колбэка явным. Если объект должен быть неизменным и заранее привязанным к конкретной операции, практичнее методное значение.
1. Меняется ли получатель при передаче методного выражения?
Да, получатель выбирается при каждом вызове как первый аргумент. Само методное выражение не привязано к конкретному экземпляру, поэтому его можно вызвать с разными значениями одного подходящего типа.
2. Как выбрать методное выражение для указательного получателя?
Нужно использовать указательный тип, поскольку метод входит в методный набор указателя, а не значения. Полученная функция принимает указатель первым аргументом; автоматическое взятие адреса, возможное при обычном вызове метода, не превращает методное выражение в функцию со значимым получателем.
3. Чем опасно сравнивать методное выражение с методным значением по сигнатуре?
Их сигнатуры различаются. Методное выражение включает получателя в список аргументов, а методное значение уже содержит получателя и потому имеет на один явный параметр меньше. Из-за этого они подходят для разных типов колбэков, даже если выполняют одну и ту же логику.