Найти в Дзене
Golang-news

Как проверить, существует ли файл с помощью Golang

Оглавление

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

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

Например, Node.js , Java , Rust , Ruby , Bash , C++ , C# , Objective-C , D , Kotlin , Dart , R , Perl , PHP и Python — это лишь некоторые из многих языков, в которые эта функциональность встроена. стандартные библиотеки.

Однако мы увидим, что очень легко воссоздать эту функциональность в Go, написав всего несколько строк кода.

Знакомство с функцией статистики

Несмотря на кажущуюся неадекватность стандартной библиотеки Go, с помощью функции очень легко проверить, существует файл или нет os.Stat.

Название функции представляет собой сокращенную версию слова «статистика» , поскольку оно предоставляет некоторые основные метаданные о файле.

Он основан на stat функции, доступной в языке программирования C в системах на базе UNIX.

В Go вы вызываете os.Stat с одним аргументом: путем к файлу, информацию о котором вы хотите получить.

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

Возвращаемые значения os.Stat

Эта функция возвращает значение, соответствующее интерфейсу os.FileInfo: она имеет методы, которые можно вызывать для получения дополнительной информации о файле, такой как его размер в байтах или время последнего изменения (используя методы и Size соответственно ModTime).

Функция os.Stat так же возвращает error значение, которое будет установлено равным определенной константе, если файл не существует.

Чтобы определить, существует ли файл по заданному пути или нет, мы можем просто сравнить значение errorс os.ErrNotExist.

Обратите внимание, что os.ErrNotExist это эквивалентно . fs.ErrNotExist  — и значение последнего фактически присваивается первому в исходном коде для"os".

Глядя на пример кода

В приведенном ниже примере показано, как точно определить, существует ли файл по заданному пути или нет, с помощью нашей надежной os.Stat функции:

-2

Здесь мы даже не присвоили os.FileInfo переменной первое возвращаемое значение, потому что это не нужно для наших целей. В конце концов, если файл не существует, вряд ли можно ожидать найти информацию о нем!

Приведенная выше функция os.IsNotExist просто возвращает значение, trueесли переданная ей ошибка равна os.ErrNotExist. Мы могли бы сами написать сравнение, но вызов этой функции более идиоматичен.

Мы также могли бы использовать errors.Is функцию, которая сравнивает любые две ошибки друг с другом, например:

errors.Is(err, fs.ErrNotExist)

(Приведенная выше функция также проверяет всю цепочку ошибок , полученных повторным вызовом не будет завернута.) errors.Unwrap по первому аргументу — хотя здесь это не должно иметь значения, так как ошибка, возвращаемая os.Stat.

Создание функции для определения существования файла

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

-3

Мы используем именованные возвращаемые значения в doesFileExist функции.

Начнем с присвоения error значения из os.Stat функции параметру err. Однако, если это значение просто означает, что файл не существует, тогда мы сбрасываем его err на nil, потому что мы используем found параметр для предоставления этой информации.

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

Точно так же мы устанавливаем только found в true в том случае, если os.Stat функция не возвращает ошибок, потому что в любом другом случае она уже будет установлена false ​​по умолчанию. Поэтому, если функция обнаруживает ошибку или файл не найден, она found всегда возвращает false.

Изменение нашей функции для проверки существования каталога

В приведенном ниже примере определяется функция, которая проверяет не только наличие пути в файловой системе, но и указывает ли этот путь на каталог (а не на обычный файл):

-4

Удобно, что IsDir метод интерфейса os.FileInfo предоставляет именно ту информацию, которая нам нужна, поэтому мы устанавливаем только в found том true случае, если возвращаемое значение этого метода также равно true.

Это означает, что если по указанному пути существует файл, но он не является каталогом, функция doesDiretoryExist вернет false значение for found и nil for err, так как этого недостаточно для выполнения нашего условия.

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

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