- Коды возврата
- Возврат результата в СИ
- Возврат результата в Golang
- Возврат результата в JavaScript
- Выводы
Подход, при котором мы возвращаем либо false
, либо данные, подразумевает, что у нас есть два состояния. Но это не всегда так.
Например, если мы возвращаем ошибку файловой системы, то обычно хотим знать, что за ошибка произошла. Например, в файловых системах в UNIXO количество ошибок превышает 100:
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
Самостоятельно пытаться догадаться, что произошло, — не лучшая идея. Так мы не сможем далеко продвинуться при работе с программой.
В этом случае появляется вопрос, как действовать — как возвращать результат. Один из самых простых вариантов — это коды возврата.
Коды возврата
Возврат ошибки связан с тем, что мы возвращаем не просто false
или undefined
. Мы возвращаем некоторое число. Оно говорит о том, какая ошибка произошла. Это работает так:
// Вызываем команду, например, удаление директории, и получаем результат
const result = files.rmdir(path);
// Проверяем, является ли результат частью списка ошибок. Перечисляем возможные варианты
if ([/* errors list */].includes(result)) {
// error
} else {
// success
}
В итоге мы узнаем, входит ли результат в список ошибок. Если всё хорошо, то мы продолжаем работать и используем тот же результат.
Проблема в том, что результат иногда может быть числовым. Тогда нам нужно выбрать лист ошибок, чтобы нормальное значение не попадало в него.
В итоге нам постоянно придется делать такие проверки — проверять большое количество возможных возвратов. Такой процесс нужно упрощать.
Возврат результата в СИ
В Си принят следующий подход возврата результата:
#include <stdio.h>
#include <errno.h>
extern int errno;
int main () {
FILE * fp;
# Открываем файл на чтение
fp = fopen("filedoesnotexist.txt", "rb");
# Делаем проверку
if (fp == NULL) { // Value of errno is: 2
# Если указатель равен нулю, то пишем, что произошла ошибка
fprintf(stderr, "Value of errno: %d\n", errno);
} else {
fclose (fp);
}
return 0;
}
Ошибка записывается в глобальную переменную, которая называется errno
. И там, например, будет цифра 2
, которая означает, что всё плохо.
Здесь мы убеждаемся, что у нас нет адекватного результата. Но по сути идет глобальное изменение среды. А глобальные переменные — это не вариант, особенно, в современных языках.
Возврат результата в Golang
Рассмотрим более продвинутый способ. Этот тот же способ, что и в СИ, но улучшенный. Он называется Golang Style.
Golang — это современный язык, который избавляет от глобальных переменных.
Смотрим пример:
package main
import (
"fmt"
"io"
"io/ioutil"
)
func main() {
// Возращается два значения: dat — данные, err — ошибка
dat, err := ioutil.ReadFile("/tmp/dat")
// Проверяем, равна ли ошибка nil
if err != nil {
fmt.Println(err.Error())
}
fmt.Print(string(dat))
}
Если ошибка не равна nil
, то ошибки нет, и всё хорошо. Если равна nil
, то мы обрабатываем ее.
Это фактически такой же подход как в CИ. Только здесь нет глобальной переменной, которая постоянно меняется. Каждая функция возвращает свой результат выполнения. Так мы двигаемся вниз по вызовам и можем строить программу.
Возврат результата в JavaScript
В JavaScript можно использовать такой же подход. Это рабочая схема, которая основана на Destructuring. У нее есть определенные недостатки, которые мы разберем в следующем уроке.
Рассмотрим пример:
// Делаем чтение, описываем данные и ошибку
const [data, err] = files.readFileSync('/unknown');
if (err === null) {
// do something with data
} else {
// handle error
}
// return [null, errors.code.ENOENT];
Если ошибка равна null
, то делаем все что хотим, если нет, то обрабатываем ошибку.
Выводы
В этом уроке мы разобрали коды возвратов. Мы рассмотрели, как выглядит результат возврата в СИ, Go и JavaScript. Также узнали, как реализовать механизм возврата кодов, чтобы они сигнализировали об определенных типах ошибок.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.