Работа с CSV в Go (Golang): полное руководство по пакету encoding/csv

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

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

Начать курс

Пакет encoding/csv в Go: полное руководство по работе с CSV-файлами

Формат CSV (Comma-Separated Values) остаётся одним из самых популярных способов обмена табличными данными. В Go (Golang) для работы с этим форматом существует стандартный пакет encoding/csv, который предоставляет удобный и производительный интерфейс для чтения и записи CSV-файлов. В этой статье мы подробно разберём все возможности пакета, от базовых операций до продвинутых техник.

Основные возможности пакета encoding/csv

Пакет encoding/csv входит в стандартную библиотеку Go и не требует установки дополнительных зависимостей. Он поддерживает:

  • Чтение CSV-файлов с настраиваемыми разделителями
  • Запись данных в CSV-формат
  • Обработку кавычек и экранирование специальных символов
  • Работу с заголовками столбцов
  • Ленивое чтение (потоковая обработка больших файлов)

Чтение CSV-файлов в Go

Для чтения CSV-файла используется структура csv.Reader. Рассмотрим базовый пример:

package main

import (
    "encoding/csv"
    "fmt"
    "log"
    "os"
)

func main() {
    // Открываем CSV-файл
    file, err := os.Open("data.csv")
    if err != nil {
        log.Fatal("Ошибка открытия файла:", err)
    }
    defer file.Close()

    // Создаем новый CSV reader
    reader := csv.NewReader(file)

    // Читаем все записи сразу
    records, err := reader.ReadAll()
    if err != nil {
        log.Fatal("Ошибка чтения CSV:", err)
    }

    // Выводим данные
    for i, record := range records {
        fmt.Printf("Строка %d: %v\n", i+1, record)
    }
}

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

Для обработки больших CSV-файлов (сотни мегабайт и более) рекомендуется использовать построчное чтение:

func readLargeCSV(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    reader := csv.NewReader(file)
    
    // Пропускаем заголовок
    header, err := reader.Read()
    if err != nil {
        return err
    }
    fmt.Println("Заголовки:", header)

    // Читаем построчно
    lineCount := 0
    for {
        record, err := reader.Read()
        if err != nil {
            break // Конец файла
        }
        // Обрабатываем запись
        fmt.Printf("Строка %d: %s | %s\n", lineCount+1, record[0], record[1])
        lineCount++
    }
    return nil
}

Настройка парсера CSV

Пакет encoding/csv позволяет гибко настраивать параметры чтения:

  • Comma — символ-разделитель (по умолчанию запятая)
  • Comment — символ комментария (строки, начинающиеся с него, игнорируются)
  • FieldsPerRecord — ожидаемое количество полей в записи
  • LazyQuotes — разрешить неэкранированные кавычки
  • TrimLeadingSpace — удалять пробелы в начале полей
func customCSVParser() {
    file, _ := os.Open("custom.csv")
    defer file.Close()

    reader := csv.NewReader(file)
    reader.Comma = ';'           // Используем точку с запятой
    reader.Comment = '#'         // Строки с # игнорируются
    reader.TrimLeadingSpace = true
    reader.LazyQuotes = true

    records, _ := reader.ReadAll()
    for _, record := range records {
        fmt.Println(record)
    }
}

Запись данных в CSV-формат

Для записи используется структура csv.Writer. Пример создания CSV-файла:

func writeCSV(filename string) error {
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    writer := csv.NewWriter(file)
    defer writer.Flush() // Важно! Сбрасываем буфер в файл

    // Записываем заголовки
    headers := []string{"Имя", "Возраст", "Город"}
    if err := writer.Write(headers); err != nil {
        return err
    }

    // Записываем данные
    data := [][]string{
        {"Анна", "28", "Москва"},
        {"Иван", "35", "Санкт-Петербург"},
        {"Мария", "22", "Казань"},
    }

    for _, row := range data {
        if err := writer.Write(row); err != nil {
            return err
        }
    }
    
    // Проверяем ошибки после записи                    

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