Первая функция
В кулинарной книге соус описывают один раз, на отдельной странице. Остальные рецепты не повторяют его по шагам, а пишут коротко: «приготовьте соус». Своя функция в программе устроена так же: её шаги записаны в одном месте, а вызвать её можно откуда угодно.
Когда одно и то же вычисление нужно в нескольких местах программы, его записывают один раз — в отдельной функции. Функция add получает два целых числа и возвращает их сумму:
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func main() {
fmt.Println(add(2, 3)) // 5
fmt.Println(add(10, -4)) // 6
}Давайте проследим за первым вызовом:
add(2, 3)отправляет выполнение в функциюadd, гдеaравно2, аbравно3.- Строка
return a + bсчитает5и возвращает это число туда, откуда функцию вызвали. fmt.Printlnполучает5и печатает его.
Второй вызов работает так же, но с другими числами, и печатает 6.
Нажмите «Следующий шаг» и следите, как управление уходит из main в add и возвращается с готовым числом.
1–4package main · import "fmt"5func add(a, b int) int {6 return a + b7}8 9func main() {10 fmt.Println(add(2, 3))11 fmt.Println(add(10, -4))12}
Чтобы напечатать результат, main сначала вызывает add(2, 3).
Объявление функции
Строка func add(a, b int) int читается слева направо:
func— ключевое слово: «объявляю функцию»;add— имя функции;(a, b int)— параметры, переменные, которые получают значения при вызове; оба имеют типint, то есть целое число;intпосле скобок — тип результата функции.
Инструкция return завершает функцию и возвращает значение выражения после неё. Выражение — это код, который даёт значение, например a + b.
Функцию можно объявить выше или ниже main. Порядок объявлений в файле не важен: компилятор читает пакет целиком.
Вызов и аргументы
В вызове add(2, 3) числа 2 и 3 — аргументы. Они и сам вызов подчиняются трём правилам:
- аргументы попадают в параметры по порядку:
2вa,3вb; - вызов заменяется значением, которое вернула функция, поэтому его можно передать в
fmt.Println; - число аргументов должно совпадать с числом параметров: вызов
add(1)компилятор отклонит с ошибкойnot enough arguments in call to add.
Здесь картинка с соусом перестаёт работать. Соус по рецепту каждый раз выходит одинаковым. А функция при каждом вызове получает свои аргументы, и её результат зависит от них.
Порядок вычислений
В одном выражении могут встретиться несколько операторов и вызовов. Давайте посмотрим на три строки:
fmt.Println(1 + 2*3) // 7
fmt.Println((1 + 2) * 3) // 9
fmt.Println(add(add(1, 2), 3)) // 6Первые две строки подчиняются правилам операторов, а третья — правилу вложенных вызовов. Разберём оба правила.
Операторы
С целыми числами работают операторы +, - и *. Порядок задают такие правила:
- как в математике,
*выполняется раньше+и-; - скобки меняют этот порядок;
- пробелы на порядок не влияют:
1 + 2*3и1+2 * 3дают одно и то же.
Слитная запись 2*3 только подсказывает читателю, что умножение выполнится первым. По этим правилам Go считает первые две строки примера так:
1 + 2*3: сначала2*3, и1 + 6даёт7.(1 + 2) * 3: скобки заставляют сначала сложить1 + 2, и3 * 3даёт9.
Вложенные вызовы
Вызов функции тоже может стоять аргументом другого вызова. Тогда Go сначала выполняет внутренний вызов, и его результат становится аргументом внешнего.
В третьей строке примера это выглядит так:
add(1, 2)возвращает3.add(3, 3)возвращает6.fmt.Printlnпечатает только6.
Частая ошибка
Функция печатает сумму вместо того, чтобы вернуть её, и тип результата у неё не указан:
package main
import "fmt"
func add(a, b int) {
fmt.Println(a + b)
}
func main() {
fmt.Println(add(2, 3)) // ✗
}add(2, 3) (no value) used as valueФункция без типа результата ничего не возвращает, поэтому её вызов нельзя передать в fmt.Println. Чтобы исправить ошибку, укажите int после скобок и верните сумму через return, как в первом примере.
Главное
- Параметры с типами стоят в скобках после имени функции, а тип результата — после скобок.
returnзавершает функцию, и вызов заменяется значением, которое она вернула.*выполняется раньше+и-, а внутренний вызов — раньше внешнего.- Функция без типа результата ничего не возвращает, и её вызов нельзя передать в
fmt.Println.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.