Ответ
Оператор return
в Go завершает выполнение текущей функции и опционально возвращает значения вызывающей стороне. Его поведение имеет несколько ключевых особенностей:
1. Возврат значений в соответствии с сигнатурой функции
Если функция объявлена с возвращаемыми типами, return
должен вернуть значения именно этих типов. Если функция не возвращает значений, return
используется для досрочного выхода из неё.
// Функция с возвращаемым значением
func sum(a, b int) int {
return a + b
}
// Функция без возвращаемых значений
func printIfPositive(n int) {
if n <= 0 {
return // Досрочный выход
}
fmt.Println(n)
}
2. Именованные возвращаемые значения и "голый" return
В Go можно именовать возвращаемые значения прямо в сигнатуре функции. Эти переменные доступны внутри функции как обычные локальные переменные и автоматически возвращаются при использовании return
без аргументов (так называемый "голый" или "naked" return
).
- Преимущество: Улучшает читаемость, особенно в функциях с несколькими возвращаемыми значениями одного типа.
- Недостаток: Чрезмерное использование "голого"
return
в длинных функциях может ухудшить понимание кода, так как неясно, какие значения возвращаются в данный момент.
func divide(a, b float64) (result float64, err error) {
if b == 0 {
err = errors.New("division by zero")
return // Возвращает (0.0, err)
}
result = a / b
return // Возвращает (result, nil)
}
3. Взаимодействие с defer
Это одна из самых важных особенностей. Отложенные (defer
) функции выполняются после того, как return
вычислил свои аргументы, но до того, как функция фактически вернёт управление.
Если функция использует именованные возвращаемые значения, defer
может их прочитать и изменить.
func getNumber() (n int) { // n инициализируется нулём
defer func() {
n++ // Этот код выполнится перед возвратом и изменит n
}()
n = 5
return n // 1. n присваивается значение 5. 2. defer увеличивает n до 6. 3. Функция возвращает 6.
}
// getNumber() вернёт 6
4. return
в функции main
Вызов return
в функции main
завершает её выполнение, что приводит к немедленному завершению всей программы. Это аналогично выходу из программы после выполнения последней строки в main
.