[БЕЗ_ЗВУКА] А теперь поговорим о функциях, как об объектах первого класса. Функция как объект первого класса означает, что вы можете присваивать функцию в какую-то переменную, принимать функцию, как аргумент в другую функцию и возвращать функцию, как результат работы какой-то функции. Ну а также иметь функцию, как поле какой-то структуры. Например, обычная функция, она определяется в отдельном блоке, то есть она имеет имя, в данном случае doNothing. Но анонимная функция, анонимная функция, она не имеет имени и определяется там, где вы захотите. Например, я объявляю анонимную функцию, то есть я не указываю имя, после ключевого слова func я сразу указываю принимающие... входящие параметры. И сразу же вызываю эту функцию на строке 14, передавая в качестве параметра строчку nobody. И она мне выведет, что что-то. anon func out: nobody. То есть nobody — это параметр анонимной функции, который я вывожу в этой Println. Также анонимную функцию можно присвоить в какую-то переменную и потом вызвать ее. То есть я вызову функцию уже, как... я обращусь к этой переменной, как к функции. Например, на строке 17 я присваиваю в переменную printer какую-то функцию, которая просто выводит текст, который в нее передали. А теперь вызываю: printer("as variable"). Давайте посмотрим. Вот, наш printer напечатал, что он был вызван, как переменная. Иногда случается так, что вам приходится много где объявлять функции, передавать их куда-то, поэтому вы можете определить специальный тип функции, например, так же, как и другие все типы, он определяется при помощи ключевого слова type, дальше вы определяете имя этого типа, ну и базовую переменную. В данном случае определение функции, сигнатура функции тоже может выступать базовым типом. При этом вы можете указать как входящие параметры, несколько входящих параметров, string, так и возвращаемые значения, string или даже вот так. Вот. То есть это корректное определение типа. Вот. Теперь давайте рассмотрим следующий вариант, что мы можем передавать функцию, как параметр, в другую функцию. Например, определим функцию worker, определим анонимную функцию и положим ее в переменную worker, которая будет принимать переменную, которая называется callback типа... какого-то типа. В данном случае мы его объявили выше, это какой-то строково-функциональный тип. Вот. Ну и потом просто будут ее вызывать. В данном случае смотрите. Я объявил worker, и теперь я передаю туда нашу функцию printer, которая будет выводить то, что в нее напечатали. Давайте посмотрим, как это работает. Вот наша функция printer вывела, что в нее передали текст as callback, то есть она была вызвана, как callback. Callback-и полезны, когда вы хотите выполнить какую-то функцию по завершении какой-то работы или в зависимости от разных условий выполнить разную логику какой-то другой функции. Теперь рассмотрим замыкание. Замыкание — это такая функция, которая обращается к переменным, которые были объявлены вне ее блока, вне ее объявления. То есть как это выглядит? Смотрите: я определяю функцию prefixer, которая принимает строчку prefix, да? И возвращает, возвращает функцию определенного типа. И я определяю теперь эту функцию — return func, я определяю входящий параметр, и теперь эта функция, то есть я определяю функцию, которая будет мне выводить то, что в нее передали, в каком-то отдельном формате. И самое интересное: она будет использовать prefix, то есть переменная, которая была объявлена не в контексте вот этом, в строчках 33‒35, а в более в контексте более высокого уровня, то есть в строчках 32‒36. Это значит замыкание, то есть функция замкнулась на что-то. Конечно, поскольку Go — язык со сборщиком мусора, переменная prefix не удалится сразу, как мы вернем значение, а будет существовать до тех пор, пока кто-то использует эту переменную. Давайте посмотрим, как это работает. Смотрите. Я объявил функцию prefixer, которая просто возвращает мне другую функцию, которая будет печатать с определенным префиксом. То есть я вызвал функцию prefixer, передал туда функцию SUCCESS, то есть «успех», и сказал, что это теперь другая функция. И эту функцию, successlogger, я вызвал с каким-то другим текстом, что «поведение ожидаемое». Давайте посмотрим, как это работает. Вот. То есть функция, которую вернула мне другая функция, сейчас напечатала мне результат. Это бывает довольно удобно, мы в практических примерах рассмотрим это.