Эта глава — сердце программирования на Go. Функции позволяют разбивать сложные задачи на мелкие, понятные и тестируемые блоки. В Go функции являются «объектами первого класса»: их можно присваивать переменным, передавать в другие функции и возвращать из них.
Функция — это независимый блок кода, который принимает входные данные (аргументы) и возвращает результат (возвращаемое значение). Функцию можно представить как «черный ящик»: мы даем ей что-то на вход, она выполняет магию внутри и выдает ответ.
Ваша вторая функция
Давайте возьмем код для вычисления среднего значения из предыдущей главы и превратим его в многоразовую функцию.
func average(xs []float64) float64 {
total := 0.0
for _, v := range xs {
total += v
}
return total / float64(len(xs))
}
Анатомия функции:
- **Ключевое слово
func**: Начало объявления. - Имя (
average): Обычно пишется вcamelCase. - Параметры (
xs []float64): Список входов в форматеимя тип. - Тип возвращаемого значения (
float64): Указывается после скобок. - Тело: Код внутри
{ }. - **Оператор
return**: Немедленно завершает функцию и отдает результат.
Теперь в main мы можем просто вызвать её:
func main() {
scores := []float64{98, 93, 77, 82, 83}
fmt.Println(average(scores))
}
Возврат нескольких значений
Одна из самых удобных особенностей Go — возможность возвращать несколько результатов. Чаще всего это используется для возврата данных и ошибки одновременно.
func divide(a, b float64) (float64, bool) {
if b == 0 {
return 0, false // Нельзя делить на ноль
}
return a / b, true
}
func main() {
result, ok := divide(10, 2)
if ok {
fmt.Println("Результат:", result)
}
}
Переменное число аргументов (Variadic Functions)
Если вы не знаете заранее, сколько аргументов придет в функцию (как в fmt.Println), используйте многоточие ...:
func add(args ...int) int {
total := 0
for _, v := range args {
total += v
}
return total
}
func main() {
fmt.Println(add(1, 2, 3, 4)) // Можно передать сколько угодно чисел
nums := []int{10, 20, 30}
fmt.Println(add(nums...)) // Или «развернуть» существующий срез
}
Замыкания (Closures)
Функции в Go могут быть анонимными (без имени) и создаваться прямо внутри других функций. Такая функция «запоминает» окружение, в котором была создана.
func makeCounter() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
next := makeCounter()
fmt.Println(next()) // 1
fmt.Println(next()) // 2
}
Рекурсия
Функция может вызывать саму себя. Классический пример — вычисление факториала :
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * factorial(x-1)
}
Управление ресурсами: Defer, Panic и Recover
Go предлагает уникальный подход к очистке ресурсов и обработке исключительных ситуаций.
Defer (Отложенный вызов)
defer гарантирует, что функция будет вызвана сразу после завершения текущей функции. Это идеально подходит для закрытия файлов или сетевых соединений.
Если вызвать
deferнесколько раз, они выполнятся в порядке LIFO (последним пришел — первым ушел).
func main() {
defer fmt.Println("Я выполнюсь в самом конце")
fmt.Println("Я выполнюсь первым")
}
Panic и Recover
panic: Вызывает аварийную остановку программы (аналог исключения). Используется только для критических ошибок.recover: Позволяет “поймать” панику и остановить падение программы. Работает только внутриdefer.
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Восстановление после ошибки:", r)
}
}()
panic("Что-то пошло не так!")
fmt.Println("Этот код никогда не выполнится")
}
Задачи
- Сигнатура: Как будет выглядеть заголовок функции
sum, принимающей срезintи возвращающей их сумму? - Четность: Напишите функцию
half, которая принимает целое число и возвращает два значения:(результат / 2, bool), гдеboolравноtrue, если число было четным. - Максимум: Напишите функцию с переменным числом аргументов
...int, которая находит наибольшее число в списке. - Фибоначчи: Напишите рекурсивную функцию для нахождения -го числа Фибоначчи.
- Формула: , где .
- Логика: В каком порядке выведутся числа 1, 2, 3 в коде ниже?
func main() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
}
Полезные ссылки
- A Tour of Go: Functions
- Go by Example: Multiple Return Values
- Defer, Panic, and Recover (Official Blog) — обязательная статья для понимания механики.