Перейти к основному содержимому
Модуль 3 · Урок 2 из 512/50 в курсе~12 min
Уроки модуля (2/5)

Множественные возвраты и именованные возвраты

В Go функция может возвращать несколько значений. Это механизм, который включает шаблон (value, error), который вы уже видели и который широко распространен вся стандартная библиотека.

Множественные возвраты

Типы возвращаемых значений указываются в круглых скобках, разделенных запятыми:

Go
func divmod(a, b int) (int, int) {
    return a / b, a % b
}

q, r := divmod(17, 5) // q=3, r=2

Они деструктурированы с множественным назначением. Чтобы отказаться от одного из значения используют _:

Go
_, r := divmod(17, 5) // solo il resto

Канонический шаблон (T, error)

Почти вся стандартная библиотека следует ему. error ВСЕГДА идет последним:

Go
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 без аргументов возвращает их («голый возвращение"):

Go
func divmod(a, b int) (q, r int) {
    q = a / b
    r = a % b
    return       // naked: ritorna q, r
}

Именованные возвраты также отображаются во всплывающих подсказках документации, поэтому они полезны. как форма встроенной документации для сложных функций, а не просто за голый возврат.

Более двух возвратов?

Ничто не мешает вам (int, int, int, error), но если вы чувствуете необходимость почти всегда это признак того, что вам следует вернуть структуру:

Go
type Result struct {
    Sum  int
    Avg  float64
    Max  int
}

func analyze(nums []int) (Result, error) { ... }

Попробуйте это

Упражнение#go.m3.l2.e1
Попыток: 0Загрузка…

Определите divmod(a, b int) (int, int), который возвращает частное и остаток.

Загрузка редактора…
Показать подсказку

Типы возвращаемых значений в круглых скобках: `(int, int)`.

Решение доступно после 3 попыток

Упражнение#go.m3.l2.e2
Попыток: 0Загрузка…

Реализуйте SafeDiv(a, b int) (int, error): если b == 0, верните (0, error.New('деление на ноль')), иначе (a/b, ноль).

Загрузка редактора…
Показать подсказку

Ошибка ВСЕГДА как последнее значение. При ошибке: нулевое значение + ошибка.

Решение доступно после 3 попыток

Quiz#go.m3.l2.e3
Готово

Что выводит эта программа, используя именованные возвраты?

Go
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 возвратов? Вероятно, вам нужна структура.