Функции и рекурсия в Go 1.21: подробное руководство
Функции и рекурсия в Go
Введение: зачем нужны функции?
Представь, что ты учишься печь пирожки. Каждый раз, когда тебе нужно испечь пирожок, ты не изобретаешь заново весь процесс: берёшь тесто, лепишь, ставишь в духовку. Ты просто используешь готовый рецепт.
В программировании функция — это такой же рецепт. Это блок кода, который выполняет одну конкретную задачу. Ты можешь использовать его снова и снова, не переписывая код каждый раз.
Когда функция вызывает саму себя — это называется рекурсия. Это как матрёшка: внутри большой матрёшки лежит поменьше, внутри неё — ещё меньше, и так до самой маленькой.
Основной синтаксис функций в Go
В Go функция начинается со слова func, затем идёт её имя, в скобках — параметры (входные данные), а после скобок — тип возвращаемого значения.
// Простая функция без параметров
func sayHello() {
fmt.Println("Привет, мир!")
}
// Функция с параметрами и возвратом значения
func sum(a int, b int) int {
return a + b
}
// Функция с двумя возвращаемыми значениями
func divide(a, b int) (int, int) {
return a / b, a % b // возвращаем частное и остаток
}
Пример 1: Семейный бюджет (сумма двух чисел)
Напишем программу, которая принимает два числа (доходы) и выводит их сумму.
package main
import "fmt"
// Функция для подсчёта суммы доходов
func sumIncome(a float64, b float64) float64 {
return a + b
}
func main() {
var income1, income2 float64
fmt.Print("Введите первый доход: ")
fmt.Scan(&income1)
fmt.Print("Введите второй доход: ")
fmt.Scan(&income2)
total := sumIncome(income1, income2)
fmt.Printf("Общая сумма доходов: %.2f\n", total)
}
Как это работает:
- Мы объявили функцию
sumIncome, которая принимает два числа и возвращает их сумму. - В
mainмы считываем числа с клавиатуры, вызываем функцию и выводим результат.
Пример 2: Сравнение температур
Функция принимает две температуры и возвращает большую из них.
package main
import "fmt"
// Функция для поиска максимума
func maxTemperature(t1 float64, t2 float64) float64 {
if t1 > t2 {
return t1
}
return t2
}
func main() {
var temp1, temp2 float64
fmt.Print("Введите первую температуру: ")
fmt.Scan(&temp1)
fmt.Print("Введите вторую температуру: ")
fmt.Scan(&temp2)
result := maxTemperature(temp1, temp2)
fmt.Printf("Большая температура: %.1f\n", result)
}
Пример 3: Проверка чётности (возврат bool)
Функция возвращает true, если число чётное, и false, если нечётное.
package main
import "fmt"
// Функция проверки чётности
func isEven(n int) bool {
return n%2 == 0
}
func main() {
var boxes int
fmt.Print("Сколько коробок произведено? ")
fmt.Scan(&boxes)
if isEven(boxes) {
fmt.Println("Число чётное — можно упаковывать в пары!")
} else {
fmt.Println("Число нечётное — одна коробка останется без пары.")
}
}
Рекурсия: когда функция вызывает саму себя
Рекурсия удобна для задач, которые можно разбить на такие же, но более маленькие подзадачи.
Важное правило: у рекурсии всегда должно быть условие выхода (базовый случай), иначе программа зациклится.
Пример 4: Реверс строки (рекурсия)
Развернём строку задом наперёд с помощью рекурсии.
package main
import "fmt"
// Рекурсивная функция для реверса строки
func reverseString(s string) string {
// Базовый случай: если строка пустая или из одного символа
if len(s) <= 1 {
return s
}
// Берём последний символ + рекурсивно разворачиваем остаток
return string(s[len(s)-1]) + reverseString(s[:len(s)-1])
}
func main() {
var text string
fmt.Print("Введите строку: ")
fmt.Scan(&text)
result := reverseString(text)
fmt.Println("Результат:", result)
}
Как это работает:
- Если строка из одного символа — возвращаем её (базовый случай).
- Иначе берём последний символ и приклеиваем к нему развёрнутую строку без последнего символа.
Пример 5: Поиск минимального элемента в списке (рекурсия)
package main
import "fmt"
// Рекурсивная функция для поиска минимума
func findMin(arr []int, n int) int {
// Базовый случай: если в массиве один элемент
if n == 1 {
return arr[0]
}
// Находим минимум в меньшей части массива
min := findMin(arr, n-1)
// Сравниваем с последним элементом
if arr[n-1] < min {
return arr[n-1]
}
return min
}
func main() {
// Пример данных: температуры за сутки
temperatures := []int{-5, 3, -8, 12, 0, 7, -2}
minTemp := findMin(temperatures, len(temperatures))
fmt.Printf("Самая низкая температура: %d°C\n", minTemp)
}
Частые ошибки новичков
- Забывают указать тип возвращаемого значения — если функция что-то возвращает, нужно обязательно написать тип после скобок.
- Путают параметры и аргументы — параметры это переменные в определении функции, аргументы — конкретные значения при вызове.
- Бесконечная рекурсия — забывают написать условие выхода. Программа будет работать, пока не закончится память.
- Используют return не во всех ветках — если функция возвращает значение, return должен быть во всех случаях (и в if, и в else).
- Пытаются изменить параметры внутри функции — в Go параметры передаются по значению (копируются). Изменение параметра не влияет на оригинальную переменную.
Итоговый пример: "Калькулятор скидки в магазине"
Напишем программу, которая рассчитывает цену со скидкой. Если сумма покупки больше 1000 рублей — скидка 10%, иначе — 5%.
package main
import "fmt"
// Функция для расчёта скидки
func calculateDiscount(price float64) float64 {
if price > 1000 {
return price * 0.9 // скидка 10%
}
return price * 0.95 // скидка 5%
}
// Рекурсивная функция для подсчёта суммы нескольких покупок
func totalWithDiscount(prices []float64, index int) float64 {
if index == len(prices) {
return 0
}
return calculateDiscount(prices[index]) + totalWithDiscount(prices, index+1)
}
func main() {
// Список покупок
purchases := []float64{500, 1200, 300, 1500}
total := totalWithDiscount(purchases, 0)
fmt.Printf("Итоговая сумма со скидками: %.2f руб.\n", total)
}
Что мы сделали:
- Функция
calculateDiscount— обычная функция для расчёта скидки на одну покупку. - Функция
totalWithDiscount— рекурсивная, проходит по всем покупкам и суммирует их со скидкой. - Базовый случай: когда дошли до конца списка — возвращаем 0.
Теперь ты знаешь, как писать функции и использовать рекурсию в Go! Пробуй решать задачи — чем больше практики, тем быстрее запомнишь.