golang

Golang Read CSV

Comma Separated Values or CSV is a data format where each line is a data record. Each record contains one or more fields, with each field separated by commas. CSV is very popular in export and import operations for databases and spreadsheets. This is because they are compressed and easy to export.

Throughout this article, we will learn how to read and write to a CSV file using the Go programming language.

Golang Encoding/CSV

To handle the CSV files in Go programming, we will use the encoding/CSV package. It comes packed with functions for reading and writing CSV files. Keep in mind a new line represents a single record in a CSV file. Each line can have one or more fields disregarding any whitespace characters.

To use the package, we can import it as:

import “encoding/csv”

We can now proceed and learn how to work with CSV files in Go.

Golang Read CSV — Line by Line

To read a CSV file using the encoding/CSV package, we use the Read() method. Let us assume we have a file called:

user_info.csv

The file contains information about users as shown in the sample snapshot below:

id,firstname,lastname,email,email2,profession
100,Blondelle,Strephon,Blondelle.Strephon@yopmail.com,Blondelle.Strephon@gmail.com,front-end developer
101,Sissy,Hutchison,Sissy.Hutchison@yopmail.com,Sissy.Hutchison@gmail.com,devops engineer
102,Babita,Loeb,Babita.Loeb@yopmail.com,Babita.Loeb@gmail.com,game developer
103,Tomasina,Letsou,Tomasina.Letsou@yopmail.com,Tomasina.Letsou@gmail.com,back-end developer

Consider the following example code:

package main
import (
    "encoding/csv"
    "fmt"
    "io"
    "log"
    "os"
)

func main() {
    file, err := os.Open("user_info.csv")
    if err != nil {
        log.Fatal(err)
    }
    reader := csv.NewReader(file)
    for {
        each_record, err := reader.Read()
        if err != nil || err == io.EOF {

            log.Fatal(err)
            break
        }
        for value := range each_record {
            fmt.Printf("%s\n", each_record[value])
        }
    }
}

Let us break down the previous code to understand better how it works.

We start by importing the required packages: encoding/csv, fmt, io, log, and os. The fmt package allows us to perform I/O operations. The log package is used to log any errors that may occur in the program.

On the other hand, the io package method is used to specify the io.Reader interface. We use the EOF error to determine the end of a data stream.

Finally, we have the os package. In our example, we use this package to read the CSV file.

In the main function, we start by opening the CSV file for reading using the os.Open() method. We then create a new reader using the csv.NewReader() method. This method takes an io.Reader type.

The next step involves using a for loop to read each record from the CSV file. Then, we check if any error is encountered. If there is any error, including an EOF, we break the loop and log the error.

The last step is to iterate over each record of the CSV file and return the values.

The previous code should return a sample output as shown below:

id
firstname
lastname
email
email2
profession
100
Blondelle
Strephon
Blondelle.Strephon@yopmail.com
Blondelle.Strephon@gmail.com
front-end developer

-------------------OUTPUT TRUNCATED-----------------------

If you want to read the CSV all at once, use the ReadAll() method instead of Read().

CSV With Custom Delimiter

Sometimes, you may come across a CSV file that does not use commas as the delimiter. Although following the format of a CSV file, files with custom delimiters can pose a challenge when parsing.

However, we can specify the comma and the comment in Go programming. Take the following example of the CSV file:

id;firstname;lastname;email;email2;profession
100;Blondelle;Strephon;Blondelle.Strephon@yopmail.com;Blondelle.Strephon@gmail.com;front-end developer
101;Sissy;Hutchison;Sissy.Hutchison@yopmail.com;Sissy.Hutchison@gmail.com;devops engineer
102;Babita;Loeb;Babita.Loeb@yopmail.com;Babita.Loeb@gmail.com;game developer
103;Tomasina;Letsou;Tomasina.Letsou@yopmail.com;Tomasina.Letsou@gmail.com;back-end developer

Although the file does follow a similar format to a CSV file, it uses semi-colons as the delimiters instead of a comma.

To parse the previous file in Go, we can run the code as shown below:

package main
import (
    "encoding/csv"
    "fmt"
    "log"
    "os"
)
func main() {
    file, err := os.Open("user_info.csv")
    if err != nil {
        log.Fatal(err)
    }
    reader := csv.NewReader(file)
    reader.Comma = ';'
    each_record, err := reader.ReadAll()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(each_record)
}

The previous code specifies a custom delimiter using the reader.Comma.

If you want to remove leading spaces, you can set the value:

reader. TrimLeadingSpace = true

Golang CSV Write

To write a CSV record to the file, we use the Write function. The record is a slice of string values, with each string representing a single field.

NOTE: Since these are buffered, you must call Flush to ensure it writes the record to the original writer.

Consider the example below:

package main
import (
    "encoding/csv"
    "log"
    "os"
)
func main() {
    new_records := [][]string{
        {"Larine", "Oriana", "[email protected]", "[email protected]", "back-end developer"}}
    file, err := os.Create("new_file.csv")
    defer file.Close()
    if err != nil {
        log.Fatal(err)
    }
    writer := csv.NewWriter(file)
    defer writer.Flush()

    for _, record := range new_records {
        if err := writer.Write(record); err != nil {
            log.Fatal(err)
        }
    }
}

The previous code creates the specified CSV files and adds the records to the file.

If you do not want to call Flush manually, you can use the WriteAll() method. It calls the Flush method automatically.

Conclusion

This guide explores how to work with CSV files using the Go encoding/CSV package. We hope you found this article helpful. Check out other Linux Hint articles to learn more tips.

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list