我有一个表示数据集的结构,我需要将其作为时间序列数据写入CSV文件。这是我到目前为止所做的。
type DataFields struct {
Field1 int,
Field2 string,
...
Fieldn int
}
func (d DataFields) String() string {
return fmt.Sprintf("%v,%v,...,%v", Field1, Field2,..., Fieldn)
}
有没有办法可以迭代结构的成员并使用它构造一个字符串对象?
性能在这里确实不是一个问题,我想知道是否有一种方法可以生成字符串而不必修改String()
函数,如果结构将来发生变化。
编辑以在下面添加我的更改:
这是我在查看下面的答案后最终得到的结果。
func (d DataFields) String() string {
v := reflect.ValueOf(d)
var csvString string
for i := 0; i < v.NumField(); i++ {
csvString = fmt.Sprintf("%v%v,", csvString, v.Field(i).Interface())
}
return csvString
}
答案 0 :(得分:2)
您要找的是reflection。 This回答解释了如何使用它来循环结构并获取值。
这是作者在另一个答案中使用的例子:
package main
import (
"fmt"
"reflect"
)
func main() {
x := struct{Foo string; Bar int }{"foo", 2}
v := reflect.ValueOf(x)
values := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
values[i] = v.Field(i).Interface()
}
fmt.Println(values)
}
您可以在go playground上看到它。
答案 1 :(得分:1)
一种方法是使用reflect
包。有一种Value.Field(int) Value
方法可能对您有用。您基本上首先使用DataField调用ValueOf(interface{}) Value
,然后在Field(int) Value
上调用Value
进行简单循环。
答案 2 :(得分:0)
另一种方法是使用code generation来为您生成序列化代码。
权衡取舍是:
Codegen更加强化,因为它大部分时间都依赖于它
关于运行外部程序(虽然这可以通过以下方式更简单)
使用go run
,因为它应该始终可用。)
每次更改数据类型时都会添加或删除
必须序列化的字段,您需要运行go generate
重新生成序列化程序代码。
另一方面,生成的代码快速而强大, 而且数据类型的变化通常很少。
反思更简单,因为它不需要考虑 重新生成代码。
另一方面,使用reflect
的代码通常是丑陋的,很难理解。当然,它会导致运行时性能损失。