web-dev-qa-db-ja.com

GoでCSVレコードを構造体にアンマーシャリングします

CSVファイルからGo構造にレコードを自動的に逆シリアル化/アンマーシャリングする方法の問題。

たとえば、私は持っています

type Test struct {
  Name string
  Surname string
  Age int
}

そしてCSVファイルにはレコードが含まれています

John;Smith;42
Piter;Abel;50

レコードを読み取るために「encoding/csv」パッケージを使用してから次のようなことを行う以外に、これらのレコードを構造化するための簡単な方法はありますか?

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

CSVレコードの構造体への自動マーシャリング(stringとintに限定)を行ったようです。これがお役に立てば幸いです。

遊び場へのリンクは次のとおりです。 http://play.golang.org/p/kwc32A5mJf

func Unmarshal(reader *csv.Reader, v interface{}) error {
    record, err := reader.Read()
    if err != nil {
        return err
    }
    s := reflect.ValueOf(v).Elem()
    if s.NumField() != len(record) {
        return &FieldMismatch{s.NumField(), len(record)}
    }
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        switch f.Type().String() {
        case "string":
            f.SetString(record[i])
        case "int":
            ival, err := strconv.ParseInt(record[i], 10, 0)
            if err != nil {
                return err
            }
            f.SetInt(ival)
        default:
            return &UnsupportedType{f.Type().String()}
        }
    }
    return nil
}

誰かがこの実装を必要としている場合は、githubパッケージを作成してみます。

12

gocarina/gocsv があり、encoding/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)
    }
}
7
pikanezi

あなたはあなた自身を焼くことができます。おそらくこのようなもの:

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)

}
1
Mike Kinney