Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write struct to csv file

Tags:

csv

go

What is an idiomatic golang way to dump the struct into a csv file provided? I am inside a func where my struct is passed as interface{}:

func decode_and_csv(my_response *http.Response, my_struct interface{})

Why interface{}? - reading data from JSON and there could be a few different structs returned, so trying to write a generic enough function.

an example of my types:

type Location []struct {
    Name                   string `json: "Name"`
    Region                 string `json: "Region"`
    Type                   string `json: "Type"`
}
like image 289
webwesen Avatar asked Oct 26 '15 23:10

webwesen


1 Answers

It would be a lot easier if you used a concrete type. You'll probably want to use the encoding/csv package, here is a relevant example; https://golang.org/pkg/encoding/csv/#example_Writer

As you can see, the Write method is expecting a []string so in order to generate this, you'll have to either 1) provide a helper method or 2) reflect my_struct. Personally, I prefer the first method but it depends on your needs. If you want to go route two you can get all the fields on the struct an use them as the column headers, then iterate the fields getting the value for each, use append in that loop to add them to a []string and then pass it to Write out side of the loop.

For the first option, I would define a ToSlice or something on each type and then I would make an interface call it CsvAble that requires the ToSlice method. Change the type in your method my_struct CsvAble instead of using the empty interface and then you can just call ToSlice on my_struct and pass the return value into Write. You could have that return the column headers as well (meaning you would get back a [][]string and need to iterate the outer dimension passing each []string into Write) or you could require another method to satisfy the interface like GetHeaders that returns a []string which is the column headers. If that were the case your code would look something like;

w := csv.NewWriter(os.Stdout)
headers := my_struct.GetHeaders()
values := my_struct.ToSlice()
if err := w.Write(headers); err != nil {
    //write failed do something
}
if err := w.Write(values); err != nil {
    //write failed do something
}

If that doesn't make sense let me know and I can follow up with a code sample for either of the two approaches.

like image 61
evanmcdonnal Avatar answered Oct 29 '22 07:10

evanmcdonnal