Comma-Separated Values (CSV) is a common textual data format that allows data to be stored in a structured tabular form. In Go, the encoding/csv package is a powerful tool for both parsing and generating CSV files. This article will guide you through the basics of using this package with practical examples.

Parsing CSV Files in Go

To parse a CSV file, you need to create a new CSV reader and then use it to read the data line by line. Here's how you can parse a CSV file step-by-step:

Basic Example of Parsing

package main

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

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

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

    // Read all records at once (excluding the CSV header)
    records, err := reader.ReadAll()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

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

In this example, we open a CSV file called data.csv, create a reader for it, and then read all the records at once. Each record is a slice of strings.

Reading CSV with Headers

If your CSV file contains a header row, you could skip it by reading it first and then processing other records.

package main

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

func main() {
    file, err := os.Open("data.csv")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()

    reader := csv.NewReader(file)

    // Read the first row for headers
    headers, err := reader.Read()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    // Print headers
    fmt.Println("Headers:", headers)

    // Read the remaining records
    for {
        record, err := reader.Read()
        if err != nil {
            break
        }
        fmt.Println(record)
    }
}

Generating CSV Files in Go

Generating CSV files is just as straightforward. You create a new CSV writer and then write each record to your file.

Basic Example of Generating

package main

import (
    "encoding/csv"
    "os"
)

func main() {
    // Create a CSV file
    file, err := os.Create("output.csv")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()

    // Create a CSV writer
    writer := csv.NewWriter(file)

    // Example records
    records := [][]string{
        {"Name", "Age", "Country"},
        {"Alice", "30", "USA"},
        {"Bob", "25", "UK"},
    }

    // Write all records
    for _, record := range records {
        if err := writer.Write(record); err != nil {
            fmt.Println("Error:", err)
        }
    }

    // Ensure all data is flushed to the file
    writer.Flush()
}

Here, we generate a CSV file named output.csv with some sample records. We create a new file with os.Create() and use a CSV writer to write each record iteratively.

Conclusion

The encoding/csv package in Go is quite efficient for handling CSV files, whether you're parsing or generating them. It's easy to read and write row by row, with or without headers, and to handle errors appropriately at each step. Understanding this process provides a strong foundation for managing CSV formatted data in your Go applications.