gpt4 book ai didi

go - 如何用马提尼输出 CSV?

转载 作者:数据小太阳 更新时间:2023-10-29 03:38:02 24 4
gpt4 key购买 nike

我想用 martini 将 CSV 数据打印到输出。目前,我一直使用 r.JSON(200, somestruct) 其中 r 是来自 github.com/的 render.Render马提尼贡献

现在我有一片结构,我想将它们打印为 CSV(将单个结构的每个字段串化并在一行中打印一个结构)。

目前,我是这样做的:

r.Data(200, []byte("id,Latitude,Longitude\n"))
for _, packet := range tour.Packets {
r.Data(200, []byte(strconv.FormatInt(packet.Id, 10)+","+strconv.FormatFloat(packet.Latitude, 'f', 6, 64)+","+strconv.FormatFloat(packet.Longitude, 'f', 6, 64)+"\n"))
}

但我不喜欢我这样做的方式,原因如下:

  • 它是直接下载的,不会打印到屏幕上。
  • 我得到 http: multiple response.WriteHeader calls
  • 我不想手动创建它(该结构有更多字段,但所有字段都是 ìnt64float64time.Time.

如何以更简单的方式实现 CSV 导出选项?

最佳答案

使用标准库。没有反射(reflection)就没有通用的解决方案,但是你可以简化它。

func handler(rw http.ResponseWriter) {
rw.Header().Add("Content-Type", "text/csv")
wr := csv.NewWriter(rw)
err := wr.Write([]string{"id", "Latitude", "Longitude"})
if err != nil {
...
}
for _, packet := range tour.Packets {
err := wr.Write([]string{
strconv.FormatInt(packet.Id, 10),
strconv.FormatFloat(packet.Latitude, 'f', 6, 64),
strconv.FormatFloat(packet.Longitude, 'f', 6, 64),
})
if err != nil {
...
}
}
}

如果您需要任何结构的通用解决方案,则需要 reflect。参见 here .

// structToStringSlice takes a struct value and
// creates a string slice of all the values in that struct
func structToStringSlice(i interface{}) []string {
v := reflect.ValueOf(i)
n := v.NumField()
out := make([]string, n)
for i := 0; i < n; i++ {
field := v.Field(i)
switch field.Kind() {
case reflect.String:
out[i] = field.String()
case reflect.Int:
out[i] = strconv.FormatInt(field.Int(), 10)
// add cases here to support more field types.
}
}
return out
}

// writeToCSV prints a slice of structs as csv to a writer
func writeToCSV(w io.Writer, i interface{}) {
wr := csv.NewWriter(w)
v := reflect.ValueOf(i)

// Get slice's element type (some unknown struct type)
typ := v.Type().Elem()
numFields := typ.NumField()
fieldSet := make([]string, numFields)
for i := 0; i < numFields; i++ {
fieldSet[i] = typ.Field(i).Name
}
// Write header row
wr.Write(fieldSet)

// Write data rows
sliceLen := v.Len()
for i := 0; i < sliceLen; i++ {
wr.Write(structToStringSlice(v.Index(i).Interface()))
}
wr.Flush()
}

那么你的例子就是:

func handler(rw http.ResponseWriter) {
....
writeToCSV(rw, tour.Packets)
}

我编写的函数仅适用于 int 或 string 字段。您可以通过将 case 添加到 structToStringSlice 中的开关来轻松地将其扩展到更多类型。参见 here用于反射(reflect)其他 Kinds 的文档。

关于go - 如何用马提尼输出 CSV?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29183152/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com