Работа с файловой системой в Go: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с файловой системой в Go: от основ до продвинутых техник

Go (Golang) — современный язык программирования, который славится своей простотой и высокой производительностью. Одной из ключевых задач, с которыми сталкивается любой разработчик, является работа с файловой системой. В этой статье мы подробно разберём, как создавать, читать, записывать файлы, управлять директориями и обрабатывать пути в Go. Вы получите практические примеры кода, которые помогут вам освоить работу с файлами быстро и эффективно.

Основные пакеты для работы с файловой системой

В Go работа с файловой системой сосредоточена в трёх основных пакетах стандартной библиотеки:

  • os — базовые операции: открытие, создание, удаление файлов и директорий.
  • io и io/ioutil — чтение и запись данных (в новых версиях Go рекомендуется использовать os вместо ioutil).
  • path/filepath — работа с путями: объединение, разбиение, получение расширений.

Перед началом работы убедитесь, что вы импортировали необходимые пакеты:

package main

import (
    "fmt"
    "os"
    "io"
    "path/filepath"
)

Чтение и запись файлов в Go

Чтение файла целиком

Самый простой способ прочитать файл — использовать функцию os.ReadFile (доступна с Go 1.16). Она возвращает срез байт и ошибку.

func readFileExample() {
    data, err := os.ReadFile("example.txt")
    if err != nil {
        fmt.Println("Ошибка чтения файла:", err)
        return
    }
    fmt.Println(string(data))
}

Запись в файл

Для записи данных в файл используйте os.WriteFile. Если файл не существует, он будет создан. Если существует — перезаписан.

func writeFileExample() {
    content := []byte("Привет, мир!\nВторая строка.")
    err := os.WriteFile("output.txt", content, 0644)
    if err != nil {
        fmt.Println("Ошибка записи:", err)
        return
    }
    fmt.Println("Файл успешно записан")
}

Построчное чтение больших файлов

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

import "bufio"

func readLineByLine() {
    file, err := os.Open("large_file.txt")
    if err != nil {
        fmt.Println("Ошибка открытия:", err)
        return
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        fmt.Println(line)
    }
    if err := scanner.Err(); err != nil {
        fmt.Println("Ошибка сканирования:", err)
    }
}

Работа с директориями в Go

Создание и удаление директорий

Для создания одной директории используйте os.Mkdir, для вложенных — os.MkdirAll.

func createDirectories() {
    // Создать одну папку
    err := os.Mkdir("mydir", 0755)
    if err != nil {
        fmt.Println("Ошибка создания папки:", err)
    }

    // Создать вложенную структуру
    err = os.MkdirAll("path/to/nested/dir", 0755)
    if err != nil {
        fmt.Println("Ошибка создания вложенных папок:", err)
    }
}

Удаление директорий выполняется функциями os.Remove (для пустых) и os.RemoveAll (для непустых).

func removeDirectories() {
    // Удалить пустую папку
    err := os.Remove("mydir")
    if err != nil {
        fmt.Println("Ошибка удаления:", err)
    }

    // Удалить папку со всем содержимым
    err = os.RemoveAll("path/to")
    if err != nil {
        fmt.Println("Ошибка рекурсивного удаления:", err)
    }
}

Чтение содержимого директории

Функция os.ReadDir возвращает список элементов в директории.

func listDirectory() {
    entries, err := os.ReadDir(".")
    if err != nil {
        fmt.Println("Ошибка чтения директории:", err)
        return
    }

    for _, entry := range entries {
        info, _ := entry.Info()
        fmt.Printf("Имя: %s, Размер: %d байт, Директория: %t\n",
            entry.Name(), info.Size(), entry.IsDir())
    }
}

Навигация по файловой системе и работа с путями

Объединение и разбор путей

Пакет path/filepath предоставляет кроссплатформенные функции для работы с путями.

func pathOperations() {
    // Объединение путей
    fullPath := filepath.Join("home", "user", "docs", "file.txt")
    fmt.Println("Полный путь:", fullPath)

    // Разделение на директорию и имя файла
    dir, file := filepath.Split(fullPath)
    fmt.Printf("Директория: %s, Файл: %s\n", dir, file)

    // Получение расширения
    ext := filepath.Ext(file)
    fmt.Println("Расширение:", ext)

    // Получение абсолютного пути
    absPath, _ := filepath.Abs(".")
    fmt.Println("Абсолютный путь:", absPath)
}

Проверка существования файла или директории

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

func fileExists(path string) bool {
    _, err := os.Stat(path)
    return err == nil
}

func checkExample() {
    if fileExists("example.txt") {
        fmt.Println("Файл существует")
    } else {
        fmt.Println("Файл не найден")
    }
}

Рекурсивный обход директорий

Для обхода всех файлов и папок в дереве директорий используйте filepath.Walk.

func walkExample() {
    err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        fmt.Printf("Путь: %s, Размер: %d\n", path, info.Size())
        return nil
    })
    if err != nil {
        fmt.Println("Ошибка обхода:", err)
    }
}

Заключение

В этой статье мы подробно рассмотрели основные аспекты работы

Блоги

Рекомендаций по книгам