Skip to content

Instantly share code, notes, and snippets.

@linw1995
Created August 20, 2021 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save linw1995/7e61ff81625848c277920f32941d2e88 to your computer and use it in GitHub Desktop.
Save linw1995/7e61ff81625848c277920f32941d2e88 to your computer and use it in GitHub Desktop.
Golang read csv data row into struct
package main
import (
"bytes"
"encoding/csv"
"fmt"
"io"
"reflect"
)
type Reader struct {
*csv.Reader
Fields []string
}
func NewReader(r io.Reader) *Reader {
rd := csv.NewReader(r)
rd.FieldsPerRecord = -1
fields, err := rd.Read()
if err != nil {
panic(err)
}
return &Reader{
Reader: rd,
Fields: fields,
}
}
func (r *Reader) ReadInto(v interface{}) (err error) {
rv := reflect.ValueOf(v)
for rv.Kind() != reflect.Ptr || rv.IsNil() {
return fmt.Errorf("Invalid type of output %s", reflect.TypeOf(v))
}
row, err := r.Read()
if err != nil {
return
}
mapping := make(map[string]string)
lenrow := len(row)
for idx, fieldname := range r.Fields {
if idx < lenrow {
mapping[fieldname] = row[idx]
} else {
mapping[fieldname] = ""
}
}
typ := reflect.TypeOf(v).Elem()
obj := rv.Elem()
for i := 0; i < typ.NumField(); i++ {
nf := typ.Field(i)
name := nf.Tag.Get("csv")
obj.FieldByName(nf.Name).SetString(mapping[name])
}
return nil
}
type Row struct {
A string `csv:"a"`
B string `csv:"b"`
}
func main() {
src := bytes.NewReader([]byte(`a,b,c
1,2,3
2,3,4`))
r := NewReader(src)
for {
var row Row
err := r.ReadInto(&row)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%#v\n", row)
}
}
@linw1995
Copy link
Author

https://play.golang.org/p/sakfw-IUyNm

main.Row{A:"1", B:"2"}
main.Row{A:"2", B:"3"}
EOF

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment