Правильный способ получить значение errno из PathError - PullRequest
1 голос
/ 28 марта 2019

Я пытаюсь определить, является ли os.PathError результатом EINVAL или ENOENT.Как правильно сделать это определение?

    res, err := os.Readlink(fpath)

    if err, ok := err.(*os.PathError); ok {
        if err.Err == os.ErrInvalid {
            // This path here. What's the correct check?
            return fpath
        }
        log.Printf("ResolveLinks error: %s", err)
        return ""
    }
    log.Printf("Resolved: %s to %s", fpath, res)
    return res

Если fpath указывает на обычный файл вместо символической ссылки, readlink должна выдать EINVAL, но моя проверка err.Err == os.ErrInvalid завершается неудачно, и регистрируется следующее:

2019/03/28 12:04:42 ResolveLinks error: readlink foo: invalid argument

Я должен распаковать PathError, но что тогда?Сравните строку ошибки?

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

Ответы [ 2 ]

1 голос
/ 28 марта 2019

err.Err имеет тип syscall.Errno, и это целочисленный тип, который вы можете преобразовать в int.Запуск этого кода в Ubuntu приводит к ошибке 22:

    if serr, ok := err.Err.(syscall.Errno); ok {
        fmt.Println(int(serr))
    }

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

, если вы просто хотите проверить файлэто символическая ссылка, вы можете использовать Lstat , чтобы получить FileInfo struct и выполнить проверку:

fi.Mode() & os.ModeSymlink != 0
0 голосов
/ 28 марта 2019

Я обнаружил, что строка ошибки будет соответствовать типу ошибки, но я не уверен (вообще), что это работает на разных платформах или даже в разных локалях.

if err, ok := err.(*os.PathError); ok {

    //EINVAL
    if err.Err.Error() == "invalid argument" {
        …

    // - OR - 

    //ENOENT
    if err.Err.Error() == "no such file or directory" {
       …
}
...