Working with CSV in Go (Golang): Complete Guide to Parsing and Writing

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Working with CSV in Go (Golang): Parsing, Writing, and Data Processing

CSV (Comma-Separated Values) is one of the most common formats for exchanging tabular data. In Go (Golang), working with CSV is implemented natively through the standard package encoding/csv, making it a convenient and performant tool. In this article, we will thoroughly examine how to read, create, and process CSV files in Go, including working with large data volumes, configuring delimiters, and error handling.



The encoding/csv Package: Basics

The encoding/csv package provides two main types: Reader for reading CSV and Writer for writing. It supports standard CSV rules (RFC 4180) and allows flexible configuration of parameters such as delimiter, comments, and quote handling.

To get started, simply import the package:

import "encoding/csv"


Reading a CSV File

Let's look at a simple example of reading a CSV file line by line:

package main

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

func main() { // Open the file file, err := os.Open("data.csv") if err != nil { panic(err) } defer file.Close()

// Create a Reader reader := csv.NewReader(file)

// Read all records records, err := reader.ReadAll() if err != nil { panic(err) }

// Output the data for i, record := range records { fmt.Printf("Row %d: %v", i, record) }}

Important: ReadAll() loads the entire file into memory. For large files, use line-by-line reading with Read().



Line-by-Line Reading of Large CSV Files

For processing large data volumes (gigabytes), use iterative reading:

reader := csv.NewReader(file)for {    record, err := reader.Read()    if err != nil {        // End of file        if err.Error() == "EOF" {            break        }        panic(err)    }    // Process the record    fmt.Println(record)}


Writing to a CSV File

Creating a CSV file is also intuitive:

package main

import ( "encoding/csv" "os")

func main() { file, err := os.Create("output.csv") if err != nil { panic(err) } defer file.Close()

writer := csv.NewWriter(file) defer writer.Flush() // Important: flush the buffer

// Write headers writer.Write([]string{"Name", "Age", "City"}) // Write data writer.Write([]string{"Alice", "30", "Moscow"}) writer.Write([]string{"Bob", "25", "Saint Petersburg"})}

Don't forget to call Flush() after all write operations, otherwise data may be lost.



Configuring the Delimiter and Other Parameters

By default, a comma is used, but you can change the delimiter, for example, to a semicolon (TSV — tabulation):

reader := csv.NewReader(file)reader.Comma = ';'  // For TSV: '\\t'

// For writing:writer := csv.NewWriter(file)writer.Comma = ';'

Other useful parameters:

  • LazyQuotes — allows quotes in non-standard places (default false)
  • FieldsPerRecord — checks the number of fields (a negative value disables the check)
  • Comment — comment character (e.g., '#'), lines starting with it are skipped
  • TrimLeadingSpace — automatic removal of leading spaces in fields

Example with settings:

reader := csv.NewReader(file)reader.Comma = '\\t'reader.Comment = '#'reader.TrimLeadingSpace = true


Error Handling and Validation

CSV files often contain errors: extra quotes, mismatched field counts, etc. The encoding/csv package provides mechanisms for handling such situations. For example, setting FieldsPerRecord to a negative value disables the check for the number of fields, which can be useful for files with an inconsistent structure.

Recommendations