To easily read and parse CSV (or TSV) files in Go, you can use two methods of encoding/csv
package:
csv.Reader.ReadAll()
to read and parse the entire file at once. Note however that a very large file may not fit into the memory.csv.Reader.Read()
to read the CSV file line by line.
See also our example of how to write data to a CSV file in Go
In the examples below, we use
data.csv
file:vegetables,fruits carrot,banana potato,strawberry
Read the entire CSV file at once
In this example, we open the CSV file, initialize csv.Reader
and read all the data into a [][]string
slice where the first index is the file’s line number and the second is an index of the comma-separated value in this line. We can do something with these data, for example, convert to an array of structs.
package main
import (
"encoding/csv"
"fmt"
"log"
"os"
)
type ShoppingRecord struct {
Vegetable string
Fruit string
}
func createShoppingList(data [][]string) []ShoppingRecord {
var shoppingList []ShoppingRecord
for i, line := range data {
if i > 0 { // omit header line
var rec ShoppingRecord
for j, field := range line {
if j == 0 {
rec.Vegetable = field
} else if j == 1 {
rec.Fruit = field
}
}
shoppingList = append(shoppingList, rec)
}
}
return shoppingList
}
func main() {
// open file
f, err := os.Open("data.csv")
if err != nil {
log.Fatal(err)
}
// remember to close the file at the end of the program
defer f.Close()
// read csv values using csv.Reader
csvReader := csv.NewReader(f)
data, err := csvReader.ReadAll()
if err != nil {
log.Fatal(err)
}
// convert records to array of structs
shoppingList := createShoppingList(data)
// print the array
fmt.Printf("%+v\n", shoppingList)
}
Output:
[{Vegetable:carrot Fruit:banana} {Vegetable:potato Fruit:strawberry}]
Read a CSV file line by line
Reading line by line is similar to reading the whole file at once, but in this case, we use csv.Reader.Read()
method to read the next line of data in the infinite loop. This loop is exited when no more data are available, i.e., io.EOF
error occurs.
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"os"
)
func main() {
// open file
f, err := os.Open("data.csv")
if err != nil {
log.Fatal(err)
}
// remember to close the file at the end of the program
defer f.Close()
// read csv values using csv.Reader
csvReader := csv.NewReader(f)
for {
rec, err := csvReader.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
// do something with read line
fmt.Printf("%+v\n", rec)
}
}
Output:
[vegetables fruits]
[carrot banana]
[potato strawberry]
Use a non-default field delimiter and read a TSV file
The standard separator for csv.Reader
is the comma, but it’s easy to change it to any rune. For instance, you can change it to the tab character \t
, and in this way, you get the TSV reader:
csvReader.Comma = '\t'