Go — лучший способ вернуть ошибку пакета на основе строки?

#go #error-handling #package

#Вперед #обработка ошибок #пакет

Вопрос:

У меня есть пакет с определенными экспортированными ошибками и метод, который анализирует строку, которая может содержать данные об ошибках. Есть ли способ вернуть экспортированную ошибку, соответствующую строке? Возможно ли это только с помощью a switch-case ?

 package foobarbaz

/* Import */

var (
    ErrFoo = errors.New("foo")
    ErrBar = errors.New("bar")
    /* More... */
)

func ParseStringWithErr(s string) (string, error) {
    // Data looks like e.g. "data:foo"
    var result string
    var err error
    result = getResultAsString(s)
    err = errors.New(getErrAsString(s)) // Will be "foo", "bar", etc... as string
    
    return result, err  // DOESN'T WORK
                        // New error won't be equivalent to the exported Errors
}
  

На самом деле это немного сложнее, чем это, поскольку проанализированные значения затем сохраняются в объекте, который затем возвращается. Возможно, что анализируемая строка не содержит данных об ошибке, и в этом случае часть getErrAsString просто не вызывается (и ошибка сохраняет свое нулевое значение <nil> , которое является правильным).

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

Ответ №1:

По сути, вы хотите error получить значение из строки, из ее строки ошибки.

Инициализируйте и используйте для этого простую карту:

 var errMap = map[string]error{}

func init() {
    for _, err := range []error{ErrFoo, ErrBar} {
        errMap[err.Error()] = err
    }
}

func LookupError(s string) (err error, ok bool) {
    err, ok = errMap[s]
    return
}
  

Тестирование:

 err, ok := LookupError("foo")
fmt.Println(err, ok, err == ErrFoo)

err, ok = LookupError("bar")
fmt.Println(err, ok, err == ErrBar)

err, ok = LookupError("baz")
fmt.Println(err, ok)
  

Какие результаты (попробуйте на Go Playground):

 foo true true
bar true true
<nil> false