将CSV记录解组到Go中的结构中

将CSV记录解组到Go中的结构中,csv,go,unmarshalling,Csv,Go,Unmarshalling,如何将CSV文件中的记录自动反序列化/反汇编到Go结构中的问题 例如,我有 type Test struct { Name string Surname string Age int } CSV文件包含记录 John;Smith;42 Piter;Abel;50 除了使用“encoding/csv”包读取记录,然后执行以下操作外,是否有一种简单的方法将这些记录解组到struct中 record, _ := reader.Read() test := Test{record[0],

如何将CSV文件中的记录自动反序列化/反汇编到Go结构中的问题

例如,我有

type Test struct {
  Name string
  Surname string
  Age int
}
CSV文件包含记录

John;Smith;42
Piter;Abel;50
除了使用“encoding/csv”包读取记录,然后执行以下操作外,是否有一种简单的方法将这些记录解组到struct中

record, _ := reader.Read()
test := Test{record[0],record[1],atoi(record[2])}

你可以自己烤。也许是这样的:

package main

import (
    "fmt"
    "strconv"
    "strings"
)

type Test struct {
    Name    string
    Surname string
    Age     int
}

func (t Test) String() string {
    return fmt.Sprintf("%s;%s;%d", t.Name, t.Surname, t.Age)
}

func (t *Test) Parse(in string) {
    tmp := strings.Split(in, ";")
    t.Name = tmp[0]
    t.Surname = tmp[1]
    t.Age, _ = strconv.Atoi(tmp[2])
}

func main() {

    john := Test{"John", "Smith", 42}
    fmt.Printf("john:%v\n", john)

    johnString := john.String()
    fmt.Printf("johnString:%s\n", johnString)

    var rebornJohn Test
    rebornJohn.Parse(johnString)
    fmt.Printf("rebornJohn:%v\n", rebornJohn)

}

似乎我已经完成了CSV记录到结构的自动封送(限于字符串和int)。希望这会有用

这里是到游乐场的链接:

func解组(reader*csv.reader,v接口{})错误{
记录,错误:=reader.Read()
如果错误!=零{
返回错误
}
s:=reflect.ValueOf(v).Elem()
如果s.NumField()!=len(记录){
返回和字段不匹配{s.NumField(),len(记录)}
}
对于i:=0;i
如果有人需要这个实现,我将尝试创建github包。

有一个可以像编码/json一样处理自定义结构的包。 您还可以为特定类型编写自定义封送拆收器和解封拆收器

例如:

type Client struct {
    Id      string `csv:"client_id"` // .csv column headers
    Name    string `csv:"client_name"`
    Age     string `csv:"client_age"`
}

func main() {
    in, err := os.Open("clients.csv")
    if err != nil {
        panic(err)
    }
    defer in.Close()

    clients := []*Client{}

    if err := gocsv.UnmarshalFile(in, &clients); err != nil {
        panic(err)
    }
    for _, client := range clients {
        fmt.Println("Hello, ", client.Name)
    }
}

不,你的模式就是要走的路。(我打赌,
record,:=Read()只是为了在这里获得简明的示例代码,但一定要处理实际代码中的错误,否则当某一天程序出现错误时,它会咬到你,你不知道为什么。)Ehh。。。我希望有一些包可以使用反射,比如xml/json解组。当然,忽略错误只是为了通过跳过不相关的代码来最小化示例的源代码。我想知道他们为什么不编写这样一个包。自己写一个可能会很有趣。我知道这是很多年后的事了,我只是想知道做这件事的好用例是什么?我觉得Go是强类型的,在大多数情况下,您会预先知道csv的模式,因此测试每行中每个字段的类型将是缓慢的/冗余的。也许是一个设计用来推断和向用户建议模式的工具?如果它是为了避免样板文件或硬编码类型转换,也许用转换方法将模式分离为结构是一种解决方案?是的,正如我在问题中所述,我使用手动封送来编写它,所以我正在寻找一些与编码/xml相同的自动封送方式。但要实现它,需要使用反射…解析CSV比使用引号字段或多行要复杂一些,作为自己项目的一部分,我为CSV制作了一个解析器来映射:如果您感兴趣,我们可以共同努力,也许还可以使用CSV解析器库。@mcuadros,但我正在使用标准包编码/CSV进行解析,因此,所有引用字段的问题都是使用标准包完成的。我的问题的主题是关于自动解组到静态结构(而不是动态映射)。你为什么要自己制作一个用于解析CSV的包?哦,我错过了这一点。顺便说一句,标准软件包太慢了。这个实现要快3-4倍,如果您使用另一个读卡器或其他输入,您必须创建一个stringreader。另一个cvs解析器实现可以在“非常好的建议”中找到!我可以使用一个方法
Read()string[]
引入接口,该方法只从CSV中读取一行。在这种情况下,我可以很容易地在阅读器的不同实现之间切换@ValentynShybanov您可以将
*csv.Reader
替换为
io.Reader
接口。
type Client struct {
    Id      string `csv:"client_id"` // .csv column headers
    Name    string `csv:"client_name"`
    Age     string `csv:"client_age"`
}

func main() {
    in, err := os.Open("clients.csv")
    if err != nil {
        panic(err)
    }
    defer in.Close()

    clients := []*Client{}

    if err := gocsv.UnmarshalFile(in, &clients); err != nil {
        panic(err)
    }
    for _, client := range clients {
        fmt.Println("Hello, ", client.Name)
    }
}