Уроки модуля (2/5)
Множественные возвраты и именованные возвраты
В Go функция может возвращать несколько значений. Это механизм, который
включает шаблон (value, error), который вы уже видели и который широко распространен
вся стандартная библиотека.
Множественные возвраты
Типы возвращаемых значений указываются в круглых скобках, разделенных запятыми:
func divmod(a, b int) (int, int) {
return a / b, a % b
}
q, r := divmod(17, 5) // q=3, r=2Они деструктурированы с множественным назначением. Чтобы отказаться от одного из
значения используют _:
_, r := divmod(17, 5) // solo il restoКанонический шаблон (T, error)
Почти вся стандартная библиотека следует ему. error ВСЕГДА идет последним:
func read(path string) ([]byte, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read %q: %w", path, err)
}
return data, nil
}Именованные возвраты
Вы можете назвать возвращаемые значения: они становятся предварительно объявленными переменными.
инициализируются нулем, а return без аргументов возвращает их («голый
возвращение"):
func divmod(a, b int) (q, r int) {
q = a / b
r = a % b
return // naked: ritorna q, r
}Именованные возвраты также отображаются во всплывающих подсказках документации, поэтому они полезны. как форма встроенной документации для сложных функций, а не просто за голый возврат.
Более двух возвратов?
Ничто не мешает вам (int, int, int, error), но если вы чувствуете необходимость
почти всегда это признак того, что вам следует вернуть структуру:
type Result struct {
Sum int
Avg float64
Max int
}
func analyze(nums []int) (Result, error) { ... }Попробуйте это
Определите divmod(a, b int) (int, int), который возвращает частное и остаток.
Показать подсказку
Типы возвращаемых значений в круглых скобках: `(int, int)`.
Решение доступно после 3 попыток
Реализуйте SafeDiv(a, b int) (int, error): если b == 0, верните (0, error.New('деление на ноль')), иначе (a/b, ноль).
Показать подсказку
Ошибка ВСЕГДА как последнее значение. При ошибке: нулевое значение + ошибка.
Решение доступно после 3 попыток
Что выводит эта программа, используя именованные возвраты?
func f() (a, b int) {
a = 1
b = 2
return
}
x, y := f()
fmt.Println(x, y)Резюме
– Несколько значений в круглых скобках: func f() (T1, T2, error).
- Соглашение:
errorВСЕГДА как последнее значение; при ошибке, нулевое значение + ошибка. - Именованные возвраты предварительно объявляют переменные и включают голые возвраты.
- Голые возвраты только в очень коротких функциях; кроме того, страдает читаемость.
- Больше 2-3 возвратов? Вероятно, вам нужна структура.