Вернуть ошибку из отложенной функции, когда ошибка уже возвращена - PullRequest
2 голосов
/ 20 сентября 2019

Обновление: теперь я думаю, что нет универсального ответа на этот вопрос.Мы можем вернуть обе ошибки, используя методику, описанную в ответе.Я думаю, что здесь главное не забыть тот случай, когда у нас есть две ошибки и как-то с ними справиться.

Примечания. В SO много вопросов о том, как вернуть ошибку из отложенной функции.Это , а не вопрос здесь.

(In Go) Что такое правильный способ вернуть ошибку от отложенной функции, когда функция уже возвращает ошибку,Для пример

func errorMaker() (err error) {
    defer func() {
        err = errors.New("Deferred error")
    }()

    err = errors.New("Some error")
    return
}
func main() {
    err := errorMaker()
    fmt.Printf("Error: %v\n", err)
}

В приведенном выше коде ошибка, возвращаемая отложенной функцией, перезаписывает ошибку, возвращенную функцией.Какой канонический способ вернуть обе ошибки?Если другой программист использует мою функцию, какой результат она может ожидать от функции, когда функция возвращает «две ошибки»?

Должен ли я использовать Обтекание ошибок для этого?

Дополнительнопримечания:

  1. Как говорит @Volker в своем комментарии, я напишу некоторую специфическую обработку приложения для этой ошибки.Потому что я знаю, что нужно делать, исходя из характера ошибок.
  2. Я думаю, что мой вопрос - если я хочу вернуть все ошибки из функции, каков наилучший способ объединить их в моем сценарии?

1 Ответ

1 голос
/ 20 сентября 2019

Отказ от ответственности: я не знаю, можно ли считать следующий совет «стандартным» или «общепринятым».

Должен ли я использовать для этого перенос ошибок?

Краткий ответ: да (я бы так и сделал).


Перейти на 1.12 и ранее

Что я делаю, когда мне нужно, чтобы мои ошибки передавали какое-то конкретное значение, без использования интерфейса error, я создаю оболочку, которая реализует интерфейс ошибок - Error() string -.Эта обертка содержит всю дополнительную информацию, которая мне нужна.

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

type MyError struct {
    DeferredError error
}

// Implements 'error' interface
func (e MyError) Error() string {
    // format to string
}

func someFunc() error {
    // might return an instance of MyError
}

...

// Caller code
err := someFunc()
if err != nil {
    if myErr, ok := err.(*MyError); ok {
        // here you can access the wrapped info
        fmt.Println(myErr.DeferredError)

    } else {
        // otherwise handle the error generically
    }
}


Go 1.13 вперед

С Go.13 вы можете использовать errors.Asразвернуть ошибку.Из официальных документов:

[Метод] As находит первую ошибку в цепочке ошибок, которая соответствует цели, и, если это так, устанавливает target для этого значения ошибки и возвращает true.Цепочка состоит из самой ошибки, за которой следует последовательность ошибок, получаемых при неоднократном вызове Unwrap.

var myErr *MyError
if errors.As(err, &myErr) {
    // here you can access the wrapped info
    fmt.Println(myErr.DeferredError)
} else {
    // otherwise handle the error generically 
}

Как говорят в документации, переменная myErr заполняется как побочный эффект вызова As.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...