Обработка ошибок

40 views
Skip to first unread message

Andrey Velikoredchanin

unread,
Mar 25, 2018, 7:37:52 AM3/25/18
to Golang
Всем привет! Из-за того, что ошибки в golang это просто объект со строкой, возник вопрос - каким образом вообще обрабатывать такие ошибки?

Вот, допустим, есть у меня некое API для JS, написанное на golang. Если при ошибке просто возвращать английский текст ошибки в ответе - это будет коряво, т.к. пользователю надо выдавать что-то написанное по русски. Ситуация еще более усложняется если сайт многоязычный.

Подскажите, пожалуйста, может есть какие-то паттерны или библиотеки которые решают эту проблему?

Спасибо.

Daniel Podolsky

unread,
Mar 25, 2018, 8:30:43 AM3/25/18
to gola...@googlegroups.com
Хорошего нет ничего

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Vladimir B

unread,
Mar 25, 2018, 1:36:56 PM3/25/18
to Golang Russian
Есть два варианта: на уровне пакета создать переменные  или создать структуры с методом Error().
В первом случае вы можете проверять ошибки на равенство переменной.
В случае со струтурами вы их сможете возвращать как ошибки и проверять по типу в коде.
Структуры и переменные-ошибки должны быть экспортируемыми для пакета (с заглавной буквы)

Пример переменной-ошибки:
var ErrAsVar = errors.New("Simple Custom Error 1")
Соответственно, вы ее можете импортировать в другом пакете и проверять в коде на равенство (err == ErrAsVar).
Но вы не можете поменять сообщение у этой ошибки. Если надо - то для этого нужны структуры.

// ZeroDivErr with different messages
type ZeroDivErr struct {
msg string
}

func (e *ZeroDivErr) Error() string {
return fmt.Sprintf("ZeroDivErr: can't divide by zero: %s", e.msg)
}

func NewZeroDivErr(msg string) *ZeroDivErr {
return &ZeroDivErr{msg}
}

Такую структуру можно проверять по типу с помощью reflect и у нее могут быть разные тексты:
if reflect.TypeOf(errTyped) == reflect.TypeOf(&ZeroDivErr{}) {...}

Пример в песочнице:


воскресенье, 25 марта 2018 г., 14:37:52 UTC+3 пользователь Andrey Velikoredchanin написал:

Alex Lurye

unread,
Mar 26, 2018, 2:43:03 AM3/26/18
to gola...@googlegroups.com
Есть разные варианты. Владимир привёл несколько из них. Посмотрите ещё, как сделаны ошибки в модуле os: все функции возвращают какие-нибудь системные ошибки, и из много разных видов, но пользователю не надо их все знать. Имеющие смысл проверки реализованы в виде специальных функций os.IsExist(err), os.IsNotExist(err) и т.д.

Есть ещё вариант удобный - вообще, это часть библиотеки gRPC, но оно и без собственно RPC отлично работает.
https://godoc.org/google.golang.org/grpc/codes - стандартизованные коды ошибок
https://godoc.org/google.golang.org/grpc/status - функции для удобной работы с ними

Возвращать так:
return status.Errorf(codes.InvalidArgument, "supplied input %s is bullshit", inputNum)

Проверять так:
if status.Code(err) == codes.InvalidArgument {
  log.Errorf("boo: %v", err)
}

Это по-прежнему обычная ошибка типа error, её можно передавать, возвращать - что угодно с ней делать, кроме интерполяции в строку (при которой код ошибки теряется). status.Code чем хороша, она возвращает codes.OK, если ей передать nil, и codes.Unknown если не инструментированную ошибку. Ну и если приложение писать с gRPC, тогда коды ошибок отлично пролезают через сеть и возвращаются клиентам.

--

Andrey Velikoredchanin

unread,
Mar 26, 2018, 2:50:40 AM3/26/18
to golang-ru
Всем спасибо за информацию!

Решил делать обработку ошибок своим классом. Сделал модуль errors_l10n. В начале работы приложения будет производиться загрузка строк для разных языков из yaml файла (по аналогии с l10n в ruby on rails), а при создании ошибки - использоваться код языка, код ошибки и произвольный набор параметров. Думаю, в будущем выделю модуль и залью его на github как самостоятельную библиотеку.

26 марта 2018 г., 9:42 пользователь 'Alex Lurye' via Golang Russian <gola...@googlegroups.com> написал:
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+unsubscribe@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages