Ce face encoding/csv.Reader
csv.NewReader(r) creează un cititor CSV peste orice io.Reader (fișier deschis, text, corpul unei cereri). rd.Read() returnează următorul rând ca slice de texte (câte unul pe coloană) și io.EOF când nu mai sunt rânduri. Câmpurile între ghilimele pot conține virgule, ghilimele dublate ("") și chiar rânduri noi.
Setări prin câmpuri, înainte de prima citire: Comma schimbă separatorul (în Excel românesc este adesea ';'), Comment ignoră rândurile care încep cu un caracter (de exemplu '#'), TrimLeadingSpace elimină spațiile de la începutul câmpurilor, FieldsPerRecord verifică numărul de coloane (implicit, toate rândurile trebuie să aibă câte coloane are primul; -1 dezactivează verificarea).
Citirea rând cu rând consumă puțină memorie, deci este potrivită pentru fișiere mari. Erorile de format sunt de tip *csv.ParseError și spun rândul și coloana.
Parametri
| Parametru | Descriere |
|---|---|
r |
Sursa datelor (io.Reader). |
Ce returnează
NewReader: *csv.Reader. Read: rândul ([]string) și o eroare (io.EOF la final).
Exemple
Exemplul 1: Citire rând cu rând
package main
import (
"encoding/csv"
"errors"
"fmt"
"io"
"strconv"
"strings"
)
func main() {
date := `nume,oras,salariu
Ana Popescu,Iași,6500
"Ionescu, Mihai",Cluj,7200
Elena,"Târgu Mureș",5800
`
rd := csv.NewReader(strings.NewReader(date))
antet, err := rd.Read()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Coloane:", antet)
total := 0
for {
rand, err := rd.Read()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
fmt.Println("eroare:", err)
return
}
salariu, _ := strconv.Atoi(rand[2])
total += salariu
fmt.Printf("%-16s %-12s %d lei\n", rand[0], rand[1], salariu)
}
fmt.Println("Total salarii:", total, "lei")
}
Rezultat
Coloane: [nume oras salariu]
Ana Popescu Iași 6500 lei
Ionescu, Mihai Cluj 7200 lei
Elena Târgu Mureș 5800 lei
Total salarii: 19500 lei
Exemplul 2: Separator ; și comentarii (export din Excel)
package main
import (
"encoding/csv"
"fmt"
"strings"
)
func main() {
date := `# export produse, 19.10.2026
cod; produs; pret
101; Cafea boabe 1kg; 89,90
102; Ceai verde; 14,50
`
rd := csv.NewReader(strings.NewReader(date))
rd.Comma = ';'
rd.Comment = '#'
rd.TrimLeadingSpace = true
for {
rand, err := rd.Read()
if err != nil {
break
}
fmt.Printf("%q\n", rand)
}
}
Rezultat
["cod" "produs" "pret"]
["101" "Cafea boabe 1kg" "89,90"]
["102" "Ceai verde" "14,50"]
Exemplul 3: Rând cu număr greșit de coloane
package main
import (
"encoding/csv"
"fmt"
"strings"
)
func main() {
rd := csv.NewReader(strings.NewReader("elev,nota\nAna,10\nRadu,9,absent\n"))
for {
rand, err := rd.Read()
if err != nil {
fmt.Println("Eroare:", err)
if pe, ok := err.(*csv.ParseError); ok {
fmt.Println("Rândul:", pe.Line)
}
break
}
fmt.Println(rand)
}
}
Rezultat
[elev nota]
[Ana 10]
Eroare: record on line 3: wrong number of fields
Rândul: 3
Greșeli frecvente
- Desparți singur rândurile cu
strings.Split(linie, ","). Un câmp ca"Ionescu, Mihai"se rupe în două; foloseșteencoding/csv. - Uiți că primul rând este antetul și îl prelucrezi ca date (de exemplu
strconv.Atoi("salariu")dă eroare). Citește-l separat înainte de buclă. - Fișierele salvate din Excel pot începe cu marcajul BOM (
\ufeff), care se lipește de numele primei coloane. Elimină-l custrings.TrimPrefix(antet[0], "\ufeff").
Comenzi înrudite
encoding/csv.Reader.ReadAll: Citește toate rândurile rămase dintr-un CSV deodată, ca [][]string; potrivit pentru fișiere mici.encoding/csv.Writer: Scrie fișiere CSV: Write adaugă un rând (cu ghilimele unde e nevoie), Flush trimite datele din buffer la destinație.encoding/csv.Writer.WriteAll: Scrie toate rândurile date deodată și apelează singur Flush; returnează eroarea, dacă apare.