やりたいこと
タグでcsvを読み取りたいのを大前提として、
csvの行としては分けられているデータを加工して(結合するなど)csvを読み込みたい
例として以下のようなcsvの姓と名を結合して構造体に持ちたいことがあった。
姓,名,年齢,職業
山田,太郎,30,エンジニア
佐藤,花子,25,デザイナー
田中,一郎,35,医師
渡辺,和子,28,教師
高橋,健二,32,自由業
実現手段
github.com/gocarina/gocsvのUnmarshalBytesToCallbackを使用する。
CSVの列に対応する構造体を定義しておいて、一度その形式でデータを受け取ってから欲しい形式に加工する形。
思ったよりは簡単に実装できるが実装サンプルが見つけられなかったので備忘録として。
コード例
ヘッダ部分の諸々は省略
type (
Person struct {
Name string
Age int
Job string
}
// 大文字にしないとgocsvから見えない
// csvの形式の構造体を定義しておく
PersonCSV struct {
FirstName string `csv:"名"`
SecondName string `csv:"姓"`
Age int `csv:"年齢"`
Job string `csv:"職業"`
}
)
func main() {
test := `姓,名,年齢,職業
山田,太郎,30,エンジニア
佐藤,花子,25,デザイナー
田中,一郎,35,医師
渡辺,和子,28,教師
高橋,健二,32,自由業`
var p []Person
if err := gocsv.UnmarshalBytesToCallback([]byte(test), func(pc PersonCSV) {
p = append(p, Person{
Name: pc.FirstName + pc.SecondName,
Age: pc.Age,
Job: pc.Job,
})
}); err != nil {
log.Fatalln(err)
}
for _, v := range p {
fmt.Println(v)
}
}
func (p Person) String() string {
return fmt.Sprintf("%s(%d) %s", p.Name, p.Age, p.Job)
}
コールバック関数が複雑になるとき
コールバック関数が複雑になるときは以下の対処法がありそう
- globalに[]Personを持たせる(あまりイケてなさそう)
- コールバック用の関数を返す関数を別で定義
- 無名関数で呼ぶための関数を定義
2の実装
// 処理が複雑な場合は関数を返すようにする
func ComplexProcess(person *[]Person) func(PersonCSV) {
return func(pc PersonCSV) {
*person = append(*person, Person{
Name: pc.FirstName + pc.SecondName,
Age: pc.Age,
Job: pc.Job,
})
// さらに何らかの処理。。。
}
}
func main() {
...
var p2 []Person
cp := ComplexProcess(&p2)
if err := gocsv.UnmarshalBytesToCallback([]byte(test), cp); err != nil {
log.Fatalln(err)
}
for _, v := range p2 {
fmt.Println(v)
}
...
}
3の実装
func ComplexProcess2(person *[]Person, personCSV PersonCSV) {
// pに値を加工して代入するような何らかの複雑な処理
*person = append(*person, Person{
Name: personCSV.FirstName + personCSV.SecondName,
Age: personCSV.Age,
Job: personCSV.Job,
})
}
func main() {
...
var p3 []Person
if err := gocsv.UnmarshalBytesToCallback([]byte(test), func(pc PersonCSV) {
ComplexProcess2(&p3, pc)
}); err != nil {
log.Fatalln(err)
}
for _, v := range p3 {
fmt.Println(v)
}
...
}
ざっくり書いたのは以下。
https://github.com/lapis2411/go-evaluation/blob/main/gocsv.go
よりよさげな対応あればコメントなどで教えて頂ければ!