Golangでcsvのパースをする時に、結構な頻度でハマること (reader.ReadAll()を使うと頻発する問題 strings.TrimSpaceを使うこと)
以下のGo言語プログラムで、"small2_bus_data.csv"が1行のみの
1, 93, 139.62957005198, 35.36604342344, 12:55:00
を使って、を読み込ませたのですが、その結果が
1 0 0 12:55:00 [{1 0001-01-01 00:00:00 +0000 UTC {0 0}}]
となってしまいます。
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
"time"
)
// 緯度経度の型定義
type LatLng struct {
Lat, Lng float64
}
// 時間と緯度経度の情報を持つ構造体
type BusData struct {
NodeID int
Time time.Time
Location LatLng
}
func main() {
// CSVファイルを開く
file, err := os.Open("small2_bus_data.csv")
if err != nil {
fmt.Println("Error:", err)
return
}
defer file.Close()
// CSVファイルの内容をパースする
reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
fmt.Println("Error:", err)
return
}
// データを格納するためのスライス
var busData []BusData
// CSVの各行を処理する
for _, record := range records {
nodeID, _ := strconv.Atoi(record[0])
lng, _ := strconv.ParseFloat(record[2], 64)
lat, _ := strconv.ParseFloat(record[3], 64)
timeStr := record[4]
fmt.Println(nodeID, lng, lat, timeStr)
// 時間のパース
var parsedTime time.Time
if timeStr != "" {
parsedTime, _ = time.Parse("15:04:05", timeStr)
}
// データを構造体に格納
data := BusData{
NodeID: nodeID,
Time: parsedTime,
Location: LatLng{
Lat: lat,
Lng: lng,
},
}
busData = append(busData, data)
}
fmt.Println(busData)
}
で、かなり、すったもんだした結果、文字列に余分なスペースが含まれていたため であることが分かりました(このくらい自動で対処して欲しいが)。
strings.TrimSpace がキモだったようです。
修正後のプログラムは以下の通り。
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
"strings"
"time"
)
// 緯度経度の型定義
type LatLng struct {
Lat, Lng float64
}
// 時間と緯度経度の情報を持つ構造体
type BusData struct {
NodeID int
Time time.Time
Location LatLng
}
func main() {
// CSVファイルを開く
file, err := os.Open("small2_bus_data.csv")
if err != nil {
fmt.Println("Error:", err)
return
}
defer file.Close()
// CSVファイルの内容をパースする
reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
fmt.Println("Error:", err)
return
}
// データを格納するためのスライス
var busData []BusData
// CSVの各行を処理する
for _, record := range records {
nodeID, _ := strconv.Atoi(record[0])
// スペースをトリムしてから実数に変換
lng, err := strconv.ParseFloat(strings.TrimSpace(record[2]), 64)
if err != nil {
fmt.Println("Error parsing lng:", err)
return
}
lat, err := strconv.ParseFloat(strings.TrimSpace(record[3]), 64)
if err != nil {
fmt.Println("Error parsing lat:", err)
return
}
timeStr := strings.TrimSpace(record[4]) // スペースをトリム
fmt.Println(nodeID, lng, lat, timeStr)
// 時間のパース
var parsedTime time.Time
if timeStr != "" {
parsedTime, err = time.Parse("15:04:05", timeStr)
if err != nil {
fmt.Println("Error parsing time:", err)
return
}
}
// データを構造体に格納
data := BusData{
NodeID: nodeID,
Time: parsedTime,
Location: LatLng{
Lat: lat,
Lng: lng,
},
}
busData = append(busData, data)
}
fmt.Println(busData)
}
出力結果は
>go run main28.go
1 139.62957005198 35.36604342344 12:55:00
[{1 0000-01-01 12:55:00 +0000 UTC {35.36604342344 139.62957005198}}]
となり、一安心です。