Go: Функции
Теория: Функции как возвращаемое значение
В Go функция — это значение. Точно так же, как переменной можно присвоить число, строку или структуру, переменной можно присвоить и функцию. Раз функция — значение, значит, её можно вернуть из другой функции.
Что значит «возвращать функцию»? Это значит, что в return мы можем не число, строку или структуру вернуть, а саму функцию. На первый взгляд звучит странно, но на деле это очень удобно: мы один раз описываем, как именно должна работать новая функция, и потом получаем её «на руки» в виде результата.
Сделаем функцию, которая просто возвращает другую функцию, печатающую сообщение.
Здесь makePrinter вернула функцию без имени (func() { ... }). Эта функция умеет печатать строку. Мы сохранили её в переменной printer и теперь можем вызывать как обычную функцию.
Возврат функции с параметрами
Можно сделать и посложнее: возвращаемая функция может принимать аргументы. Например, пусть мы заранее «сконфигурируем» приветствие, а потом просто будем передавать имя.
Смысл такой: функция greeter «запоминает» слово приветствия и возвращает функцию, которая его использует. В итоге мы получаем разные функции — hello и bonjour — каждая со своим заранее выбранным поведением.
Возврат функции с внутренним состоянием
Иногда хочется не только вернуть функцию, но и чтобы она хранила у себя какое-то состояние. Это очень полезно. Например, сделаем счётчик.
Здесь переменная count не пропадает после выхода из makeCounter, потому что возвращаемая функция продолжает её использовать. Это называется замыкание. У каждого вызова makeCounter будет своё собственное хранилище count.
Ещё пример: фабрика умножителей
Допустим, нам часто нужно умножать числа на разные коэффициенты. Вместо того чтобы всё время писать x * 2, x * 3, x * 10, мы можем создать «фабрику функций»:
Мы заранее фиксируем множитель, а дальше получаем готовые функции «умножитель на 2», «умножитель на 3» и так далее.
Где это реально применяется
- Настраиваемые обработчики. В веб-фреймворках часто нужно вернуть функцию-обработчик HTTP-запроса, в которую уже «зашиты» какие-то данные или настройки.
- Фабрики и конструкторы. Когда нужно вернуть готовый «инструмент» с определённым поведением.
- Инкапсуляция состояния. Счётчики, кэши, трекеры — всё это удобно делать через возвращаемые функции.
- Декораторы. Можно возвращать новую функцию, которая оборачивает старую, добавляя проверку, логирование или обработку ошибок.
Функции как возвращаемое значение — это способ создавать новые функции «на лету». Мы можем один раз описать, как они должны работать, и потом получать разные варианты с нужными настройками. Это даёт гибкость: можно хранить внутри функции состояние, можно заранее фиксировать параметры, можно возвращать функции-обработчики прямо из фабрик.
Вместо того чтобы писать кучу повторяющегося кода, мы создаём функцию, которая делает функции. Это и есть главное удобство.


