Практика 4. Функции, несколько результатов и closures
Цель
Научиться выделять вычисления в функции, использовать несколько возвращаемых
значений, variadic-параметры, функции как значения, closures и defer.
Общие требования
- создайте модуль
example.com/practice-04; - имена функций и переменных пишите на английском языке;
- функции вычисления не должны самостоятельно печатать результат;
- ошибочные входные данные обрабатывайте явно;
- выполните
go fmt ./...,go test ./...иgo vet ./....
A. Разминка
Задание 1. Минимум и максимум
Напишите две функции:
func min(a, b int) intfunc max(a, b int) intВызовите их для положительных, отрицательных и одинаковых чисел.
Задание 2. Чётность
Напишите:
func isEven(number int) boolВ main выведите результат для чисел от -3 до 3.
Задание 3. Деление с проверкой
Создайте функцию:
func divide(dividend, divisor int) (quotient int, remainder int, ok bool)Если делитель равен нулю, функция должна вернуть нулевые значения и false.
Иначе — частное, остаток и true.
Проверьте вызовы:
divide(17, 5);divide(20, 4);divide(10, 0).
Задание 4. Разложение времени
Напишите функцию:
func splitSeconds(total int) (hours, minutes, seconds int)Для отрицательного входа возвращайте нулевые результаты. Примеры:
0 → 0:00:0065 → 0:01:053661 → 1:01:01Форматирование выполняйте в main, а не внутри функции.
B. Основные задания
Задание 5. Среднее значение
Реализуйте variadic-функцию:
func average(values ...float64) (float64, bool)Требования:
- пустой набор возвращает
0, false; - непустой — среднее и
true; - функция ничего не печатает.
Проверьте обычные аргументы и готовый slice:
fmt.Println(average(4, 5, 3))
values := []float64{4.5, 4.7, 4.2}fmt.Println(average(values...))Задание 6. Выбор операции
Создайте функции:
func add(a, b float64) float64func subtract(a, b float64) float64func multiply(a, b float64) float64И функцию выбора:
func selectOperation(name string) (func(float64, float64) float64, bool)Она должна поддерживать add, subtract, multiply. Для неизвестного имени
верните nil, false. Перед вызовом результата обязательно проверьте bool.
Задание 7. Функция высшего порядка
Напишите:
func transform(values []int, operation func(int) int) []intОна возвращает новый slice и не изменяет исходный. Примените её для:
- удвоения;
- возведения в квадрат;
- изменения знака.
Хотя slices подробно изучаются в следующей лекции, здесь достаточно перебора
через range и добавления через append.
Задание 8. Closure-счётчик
Реализуйте:
func newCounter(start int, step int) func() intКаждый вызов возвращённой функции должен увеличивать состояние на step и
возвращать новое значение.
Создайте два независимых счётчика:
byOne := newCounter(0, 1)byTen := newCounter(100, 10)Докажите выводом, что их состояния независимы.
Задание 9. Порядок defer
Напишите функцию, которая выводит:
startworkfinish 3finish 2finish 1Используйте три defer. Затем создайте эксперимент, показывающий разницу между:
defer fmt.Println(value)и:
defer func() { fmt.Println(value)}()Кратко объясните результат в README.md.
C. Проект «Операции над задачами»
Продолжите сквозной проект. Пока каждая задача представлена названием и приоритетом в отдельных slices:
titles := []string{ "Подготовить отчёт", "Проверить почту", "Исправить ошибку", "Обновить документацию",}
priorities := []int{5, 2, 8, 3}Реализуйте функции:
func validPriority(priority int) boolfunc priorityLabel(priority int) (string, bool)func averagePriority(priorities ...int) (float64, bool)func countValidPriorities(priorities ...int) intfunc formatTask(number int, title string, priority int) (string, bool)Правила:
- допустимый приоритет — 1–5;
- приоритет 1 — низкий;
- 2–3 — обычный;
- 4 — высокий;
- 5 — критический;
- некорректные приоритеты не входят в среднее;
formatTaskне печатает, а возвращает готовую строку;- если title пуст после
strings.TrimSpace, задача считается некорректной; - если длины
titlesиprioritiesразличаются, программа выводит ошибку и завершает работу до обхода данных.
Пример вывода:
1. Подготовить отчёт [критический]2. Проверить почту [обычный]3. пропущена: некорректный приоритет 84. Обновить документацию [обычный]
Корректных задач: 3Средний приоритет: 3.33Дополнительная часть
Создайте функцию:
func makePriorityFilter(minimum int) func(int) boolОна возвращает closure, проверяющий, что приоритет корректен и не меньше
minimum. Используйте фильтры для высоких (4) и критических (5) задач.
Структура сдачи
practice-04/├── go.mod├── main.go└── README.mdКритерии оценивания
| Критерий | Баллы |
|---|---|
| Простые функции и несколько результатов | 0–3 |
| Variadic-функции | 0–2 |
| Функции как значения | 0–3 |
Closure и defer | 0–3 |
| Проект и декомпозиция | 0–4 |
| Стиль и проверки инструментами | 0–1 |
| Максимум | 16 |
Вопросы для защиты
- Что входит в сигнатуру функции?
- Почему
divideвозвращает дополнительныйbool? - Как передать slice в variadic-функцию?
- Что произойдёт при вызове
nil-функции? - Что такое closure?
- Когда вычисляются аргументы
defer? - В каком порядке выполняются несколько
defer? - Почему функция вычисления не должна без необходимости печатать результат?