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

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

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

Начать курс

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

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

В этой статье мы подробно разберём все возможности пакета encoding/csv на практических примерах. Вы узнаете, как читать CSV-файлы построчно и целиком, записывать данные, настраивать параметры парсинга и обрабатывать типичные ошибки.

Установка и импорт

Пакет encoding/csv входит в стандартную библиотеку Go, поэтому дополнительная установка не требуется. Для использования достаточно импортировать его в ваш код:

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

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

Самый простой способ прочитать CSV — использовать csv.NewReader и метод ReadAll, который возвращает все записи в виде среза срезов строк.

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

    reader := csv.NewReader(file)
    records, err := reader.ReadAll()
    if err != nil {
        panic(err)
    }

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

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

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

    reader := csv.NewReader(file)
    reader.LazyQuotes = true // разрешает нестрогий парсинг кавычек

    for {
        record, err := reader.Read()
        if err != nil {
            break // конец файла или ошибка
        }
        fmt.Println(record)
    }
}

Запись CSV-файлов

Для записи данных используется csv.NewWriter. Метод Write записывает одну запись, а WriteAll — сразу все. Не забудьте вызвать Flush() для сброса буфера.

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

    writer := csv.NewWriter(file)
    defer writer.Flush()

    data := [][]string{
        {"Имя", "Возраст", "Город"},
        {"Анна", "28", "Москва"},
        {"Иван", "35", "Санкт-Петербург"},
    }

    for _, record := range data {
        if err := writer.Write(record); err != nil {
            panic(err)
        }
    }
}

Настройка разделителя и экранирования

По умолчанию encoding/csv использует запятую как разделитель и двойные кавычки для экранирования. Вы можете изменить эти настройки через поля структуры Reader и Writer:

func customSettings() {
    // Чтение TSV (Tab-Separated Values)
    file, _ := os.Open("data.tsv")
    defer file.Close()

    reader := csv.NewReader(file)
    reader.Comma = '\t' // табуляция вместо запятой
    reader.Comment = '#' // игнорировать строки, начинающиеся с #

    records, _ := reader.ReadAll()
    fmt.Println(records)
}

Полезные поля для настройки:

  • Comma — символ-разделитель (по умолчанию ',')
  • Comment — символ комментария (строки с этим символом в начале игнорируются)
  • LazyQuotes — разрешает нестрогий парсинг кавычек
  • TrimLeadingSpace — удаляет пробелы в начале полей
  • FieldsPerRecord — ожидаемое количество полей (0 — не проверять)

Обработка ошибок

Пакет encoding/csv возвращает ошибки типа *csv.ParseError, которые содержат номер строки и столбца, где произошла проблема. Это очень удобно для отладки:

func errorHandling(filename string) {
    file, _ := os.Open(filename)
    defer file.Close()

    reader := csv.NewReader(file)
    for {
        record, err := reader.Read()
        if err != nil {
            if parseErr, ok := err.(*csv.ParseError); ok {
                fmt.Printf("Ошибка в строке %d, столбце %d: %v\n",
                    parseErr.Line, parseErr.Column, parseErr.Err)
            } else {
                fmt.Println("Ошиб                    

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