英文:
Write struct to csv file
问题
将结构体转储到CSV文件的惯用方式是什么?我在一个函数中,该函数接收一个作为interface{}传递的结构体:
func decode_and_csv(my_response *http.Response, my_struct interface{})
为什么使用interface{}?因为从JSON中读取数据时可能返回几种不同的结构体,所以我试图编写一个足够通用的函数。
这是我的类型的一个示例:
type Location []struct {
Name string `json:"Name"`
Region string `json:"Region"`
Type string `json:"Type"`
}
请注意,我只提供翻译服务,不会回答关于翻译内容的问题。
英文:
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"`
}
答案1
得分: 36
如果你使用具体类型会更容易一些。你可能会想要使用encoding/csv
包,这里有一个相关的示例:https://golang.org/pkg/encoding/csv/#example_Writer
正如你所看到的,Write
方法期望一个[]string
类型的参数,所以为了生成这个参数,你需要做以下两种方法之一:1)提供一个辅助方法,或者2)使用反射来获取my_struct
的字段。个人而言,我更喜欢第一种方法,但这取决于你的需求。如果你选择第二种方法,你可以将结构体的所有字段作为列标题,然后迭代字段,获取每个字段的值,在循环中使用append
将它们添加到一个[]string
中,然后在循环外将其传递给Write
方法。
对于第一种选项,我会在每个类型上定义一个ToSlice
方法,然后创建一个名为CsvAble
的接口,要求实现ToSlice
方法。在你的方法中,将类型改为my_struct CsvAble
,而不是使用空接口,然后你可以直接在my_struct
上调用ToSlice
方法,并将返回值传递给Write
方法。你可以让ToSlice
方法返回列标题(这意味着你将得到一个[][]string
,需要迭代外部维度,将每个[]string
传递给Write
方法),或者你可以要求另一个方法满足接口,比如GetHeaders
方法,它返回一个[]string
,表示列标题。如果是这样的话,你的代码将如下所示:
w := csv.NewWriter(os.Stdout)
headers := my_struct.GetHeaders()
values := my_struct.ToSlice()
if err := w.Write(headers); err != nil {
// 写入失败,做一些处理
}
if err := w.Write(values); err != nil {
// 写入失败,做一些处理
}
如果这不太清楚,请告诉我,我可以提供两种方法中的任何一种的代码示例。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论